int stub_pid1(sd_id128_t uuid) {
enum {
STATE_RUNNING,
STATE_REBOOT,
STATE_POWEROFF,
} state = STATE_RUNNING;
sigset_t fullmask, oldmask, waitmask;
usec_t quit_usec = USEC_INFINITY;
pid_t pid;
int r;
/* The new environment we set up, on the stack. */
char new_environment[] =
"container=systemd-nspawn\0"
"container_uuid=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
/* Implements a stub PID 1, that reaps all processes and processes a couple of standard signals. This is useful
* for allowing arbitrary processes run in a container, and still have all zombies reaped. */
assert_se(sigfillset(&fullmask) >= 0);
assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0);
pid = fork();
if (pid < 0)
return log_error_errno(errno, "Failed to fork child pid: %m");
if (pid == 0) {
/* Return in the child */
assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0);
setsid();
return 0;
}
reset_all_signal_handlers();
log_close();
close_all_fds(NULL, 0);
log_open();
/* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also,
* set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ
* find them set. */
sd_id128_to_string(uuid, new_environment + sizeof(new_environment) - SD_ID128_STRING_MAX);
reset_environ(new_environment, sizeof(new_environment));
rename_process("STUBINIT");
assert_se(sigemptyset(&waitmask) >= 0);
assert_se(sigset_add_many(&waitmask,
SIGCHLD, /* posix: process died */
SIGINT, /* sysv: ctrl-alt-del */
SIGRTMIN+3, /* systemd: halt */
SIGRTMIN+4, /* systemd: poweroff */
SIGRTMIN+5, /* systemd: reboot */
SIGRTMIN+6, /* systemd: kexec */
SIGRTMIN+13, /* systemd: halt */
SIGRTMIN+14, /* systemd: poweroff */
SIGRTMIN+15, /* systemd: reboot */
SIGRTMIN+16, /* systemd: kexec */
-1) >= 0);
/* Note that we ignore SIGTERM (sysv's reexec), SIGHUP (reload), and all other signals here, since we don't
* support reexec/reloading in this stub process. */
for (;;) {
siginfo_t si;
usec_t current_usec;
si.si_pid = 0;
r = waitid(P_ALL, 0, &si, WEXITED|WNOHANG);
if (r < 0) {
r = log_error_errno(errno, "Failed to reap children: %m");
goto finish;
}
current_usec = now(CLOCK_MONOTONIC);
if (si.si_pid == pid || current_usec >= quit_usec) {
/* The child we started ourselves died or we reached a timeout. */
if (state == STATE_REBOOT) { /* dispatch a queued reboot */
(void) reboot(RB_AUTOBOOT);
r = log_error_errno(errno, "Failed to reboot: %m");
goto finish;
} else if (state == STATE_POWEROFF)
(void) reboot(RB_POWER_OFF); /* if this fails, fall back to normal exit. */
if (si.si_pid == pid && si.si_code == CLD_EXITED)
r = si.si_status; /* pass on exit code */
else
r = 255; /* signal, coredump, timeout, … */
goto finish;
}
if (si.si_pid != 0)
/* We reaped something. Retry until there's nothing more to reap. */
continue;
//.........这里部分代码省略.........
/**
* Set up log file and run in the backgroud
*/
void daemonize()
{
#ifdef WINDOWS
if (!debug) {
int fd;
FILE *pidfh;
if ((fd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0644)) == -1) {
perror("Can't open log file");
exit(1);
}
if (strcmp(pidfile, "")) {
// Write out the pid file, before we redirect STDERR to the log.
if ((pidfh = fopen(pidfile, "w")) == NULL) {
perror("Can't open pid file for writing");
exit(1);
}
fprintf(pidfh, "%d\n", GetCurrentProcessId());
fclose(pidfh);
}
dup2(fd, 2);
close(fd);
applog = stderr;
}
#else // WINDOWS
if (!debug) {
int pid, fd;
FILE *pidfh;
if ((fd = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0644)) == -1) {
perror("Can't open log file");
exit(1);
}
if ((pid = fork()) == -1) {
perror("Couldn't fork");
exit(1);
} else if (pid > 0) {
parent = 1;
exit(0);
}
if (strcmp(pidfile, "")) {
// Write out the pid file, before we redirect STDERR to the log.
if ((pidfh = fopen(pidfile, "w")) == NULL) {
perror("Can't open pid file for writing");
exit(1);
}
fprintf(pidfh, "%d\n", getpid());
fclose(pidfh);
}
setsid();
dup2(fd, 2);
close(fd);
for (fd = 0; fd < 30; fd++) {
if ((fd != 2) && (fd != listener)) {
close(fd);
}
}
#ifdef VMS
chdir("SYS$LOGIN");
#else
chdir("/");
#endif
umask(0);
applog = stderr;
}
nice(-20);
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART;
act.sa_handler = gotsig;
sigaction(SIGINT, &act, NULL);
sigaction(SIGTERM, &act, NULL);
act.sa_handler = gotpipe;
sigaction(SIGPIPE, &act, NULL);
act.sa_handler = SIG_IGN;
sigaction(SIGCHLD, &act, NULL);
}
#endif // WINDOWS
}
开发者ID:shoki,项目名称:uftp,代码行数:86,代码来源:proxy_init.c
示例8: schedule_unload
int schedule_unload(pid_t pid, FAR struct binary_s *bin)
{
struct sigaction act;
struct sigaction oact;
sigset_t sigset;
irqstate_t flags;
int errorcode;
int ret;
/* Make sure that SIGCHLD is unmasked */
(void)sigemptyset(&sigset);
(void)sigaddset(&sigset, SIGCHLD);
ret = sigprocmask(SIG_UNBLOCK, &sigset, NULL);
if (ret != OK)
{
/* The errno value will get trashed by the following debug output */
errorcode = get_errno();
bvdbg("ERROR: sigprocmask failed: %d\n", ret);
goto errout;
}
/* Add the structure to the list. We want to do this *before* connecting
* the signal handler. This does, however, make error recovery more
* complex if sigaction() fails below because then we have to remove the
* unload structure for the list in an unexpected context.
*/
unload_list_add(pid, bin);
/* Register the SIGCHLD handler */
act.sa_sigaction = unload_callback;
act.sa_flags = SA_SIGINFO;
(void)sigfillset(&act.sa_mask);
(void)sigdelset(&act.sa_mask, SIGCHLD);
ret = sigaction(SIGCHLD, &act, &oact);
if (ret != OK)
{
/* The errno value will get trashed by the following debug output */
errorcode = get_errno();
bvdbg("ERROR: sigaction failed: %d\n" , ret);
/* Emergency removal from the list */
flags = irqsave();
if (unload_list_remove(pid) != bin)
{
blldbg("ERROR: Failed to remove structure\n");
}
goto errout;
}
return OK;
errout:
set_errno(errorcode);
return ERROR;
}
void CnxtAdslLEDTask(void *sem)
{
BOOL HandShakeLED;
BOOL ShowtimeLED;
struct task_struct *tsk = current ;
tsk->session = 1 ;
tsk->pgrp = 1 ;
#if defined (CONFIG_CNXT_GSHDSL) || defined (CONFIG_CNXT_GSHDSL_MODULE)
strcpy ( tsk->comm, "CnxtGshdslLEDTask" ) ;
#else
strcpy ( tsk->comm, "CnxtAdslLEDTask" ) ;
#endif
/* sigstop and sigcont will stop and wakeup kupdate */
spin_lock_irq(&tsk->sigmask_lock);
sigfillset(&tsk->blocked);
siginitsetinv(¤t->blocked, sigmask(SIGCONT) | sigmask(SIGSTOP));
recalc_sigpending(tsk);
spin_unlock_irq(&tsk->sigmask_lock);
up((struct semaphore *)sem);
TaskDelayConnect ( GP_TIMER_DMT_LED ) ;
while(1)
{
/* Condensed Showtime State to two Booleans - In Showtime and In Training */
ShowtimeLED= FALSE;
HandShakeLED= FALSE;
switch (HWSTATE.dwLineStatus)
{
case HW_IO_MODEM_STATUS_ACTIVATED:
ShowtimeLED= TRUE;
break;
case HW_IO_MODEM_STATUS_CHANNEL_ANALYSIS:
case HW_IO_MODEM_STATUS_TRANSCEIVER_TRAINING:
case HW_IO_MODEM_STATUS_EXCHANGE:
case HW_IO_MODEM_STATUS_ACTIVATION:
HandShakeLED= TRUE;
break;
}
/* Blink Showtime LED if in Training */
if (ShowtimeLED || HandShakeLED)
{
WriteGPIOData( GPOUT_SHOWTIME_LED,LED_ON );
}
/* This logic is for a blinking Showtime LED */
if (!ShowtimeLED)
{
WriteGPIOData( GPOUT_SHOWTIME_LED,LED_OFF );
}
TaskDelayMsec(LED_DELAY_PERIOD);
}
}
int
_sigaction(int sig, const struct sigaction * act, struct sigaction * oact)
{
int ret = 0;
struct sigaction gact;
/* Check if the signal number is out of range: */
if (sig < 1 || sig > NSIG) {
/* Return an invalid argument: */
errno = EINVAL;
ret = -1;
} else {
if (_thread_initial == NULL)
_thread_init();
/*
* Check if the existing signal action structure contents are
* to be returned:
*/
if (oact != NULL) {
/* Return the existing signal action contents: */
oact->sa_handler = _thread_sigact[sig - 1].sa_handler;
oact->sa_mask = _thread_sigact[sig - 1].sa_mask;
oact->sa_flags = _thread_sigact[sig - 1].sa_flags;
}
/* Check if a signal action was supplied: */
if (act != NULL) {
/* Set the new signal handler: */
_thread_sigact[sig - 1].sa_mask = act->sa_mask;
_thread_sigact[sig - 1].sa_flags = act->sa_flags;
_thread_sigact[sig - 1].sa_handler = act->sa_handler;
}
/*
* Check if the kernel needs to be advised of a change
* in signal action:
*/
if (act != NULL && sig != _SCHED_SIGNAL && sig != SIGCHLD &&
sig != SIGINFO) {
/*
* Ensure the signal handler cannot be interrupted
* by other signals. Always request the POSIX signal
* handler arguments.
*/
sigfillset(&gact.sa_mask);
gact.sa_flags = SA_SIGINFO | SA_RESTART;
/*
* Check if the signal handler is being set to
* the default or ignore handlers:
*/
if (act->sa_handler == SIG_DFL ||
act->sa_handler == SIG_IGN)
/* Specify the built in handler: */
gact.sa_handler = act->sa_handler;
else
/*
* Specify the thread kernel signal
* handler:
*/
gact.sa_handler = (void (*) ()) _thread_sig_handler;
/* Change the signal action in the kernel: */
if (__sys_sigaction(sig,&gact,NULL) != 0)
ret = -1;
}
}
/* Return the completion status: */
return (ret);
}
void Subprocess::spawnInternal(
std::unique_ptr<const char*[]> argv,
const char* executable,
Options& options,
const std::vector<std::string>* env,
int errFd) {
// Parent work, pre-fork: create pipes
std::vector<int> childFds;
// Close all of the childFds as we leave this scope
SCOPE_EXIT {
// These are only pipes, closing them shouldn't fail
for (int cfd : childFds) {
CHECK_ERR(::close(cfd));
}
};
int r;
for (auto& p : options.fdActions_) {
if (p.second == PIPE_IN || p.second == PIPE_OUT) {
int fds[2];
// We're setting both ends of the pipe as close-on-exec. The child
// doesn't need to reset the flag on its end, as we always dup2() the fd,
// and dup2() fds don't share the close-on-exec flag.
#if FOLLY_HAVE_PIPE2
// If possible, set close-on-exec atomically. Otherwise, a concurrent
// Subprocess invocation can fork() between "pipe" and "fnctl",
// causing FDs to leak.
r = ::pipe2(fds, O_CLOEXEC);
checkUnixError(r, "pipe2");
#else
r = ::pipe(fds);
checkUnixError(r, "pipe");
r = fcntl(fds[0], F_SETFD, FD_CLOEXEC);
checkUnixError(r, "set FD_CLOEXEC");
r = fcntl(fds[1], F_SETFD, FD_CLOEXEC);
checkUnixError(r, "set FD_CLOEXEC");
#endif
pipes_.emplace_back();
Pipe& pipe = pipes_.back();
pipe.direction = p.second;
int cfd;
if (p.second == PIPE_IN) {
// Child gets reading end
pipe.pipe = folly::File(fds[1], /*owns_fd=*/ true);
cfd = fds[0];
} else {
pipe.pipe = folly::File(fds[0], /*owns_fd=*/ true);
cfd = fds[1];
}
p.second = cfd; // ensure it gets dup2()ed
pipe.childFd = p.first;
childFds.push_back(cfd);
}
}
// This should already be sorted, as options.fdActions_ is
DCHECK(std::is_sorted(pipes_.begin(), pipes_.end()));
// Note that the const casts below are legit, per
// http://pubs.opengroup.org/onlinepubs/009695399/functions/exec.html
char** argVec = const_cast<char**>(argv.get());
// Set up environment
std::unique_ptr<const char*[]> envHolder;
char** envVec;
if (env) {
envHolder = cloneStrings(*env);
envVec = const_cast<char**>(envHolder.get());
} else {
envVec = environ;
}
// Block all signals around vfork; see http://ewontfix.com/7/.
//
// As the child may run in the same address space as the parent until
// the actual execve() system call, any (custom) signal handlers that
// the parent has might alter parent's memory if invoked in the child,
// with undefined results. So we block all signals in the parent before
// vfork(), which will cause them to be blocked in the child as well (we
// rely on the fact that Linux, just like all sane implementations, only
// clones the calling thread). Then, in the child, we reset all signals
// to their default dispositions (while still blocked), and unblock them
// (so the exec()ed process inherits the parent's signal mask)
//
// The parent also unblocks all signals as soon as vfork() returns.
sigset_t allBlocked;
r = sigfillset(&allBlocked);
checkUnixError(r, "sigfillset");
sigset_t oldSignals;
r = pthread_sigmask(SIG_SETMASK, &allBlocked, &oldSignals);
checkPosixError(r, "pthread_sigmask");
SCOPE_EXIT {
// Restore signal mask
r = pthread_sigmask(SIG_SETMASK, &oldSignals, nullptr);
CHECK_EQ(r, 0) << "pthread_sigmask: " << errnoStr(r); // shouldn't fail
};
// Call c_str() here, as it's not necessarily safe after fork.
//.........这里部分代码省略.........
请发表评论