/** * Run the daemon and handle unix signals */ static void run() { sigset_t set; /* handle SIGINT and SIGTERM in this handler */ sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); sigprocmask(SIG_BLOCK, &set, NULL); while (TRUE) { int sig; sig = sigwaitinfo(&set, NULL); if (sig == -1) { if (errno == EINTR) { /* ignore signals we didn't wait for */ continue; } DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno)); return; } switch (sig) { case SIGINT: { DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down"); charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); return; } case SIGTERM: { DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down"); charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); return; } } } }
static void luasandbox_timer_stop_one(luasandbox_timer * lt, struct timespec * remaining) { static struct timespec zero = {0, 0}; struct itimerspec its; timer_gettime(lt->timer, &its); if (remaining) { *remaining = its.it_value; } its.it_value = zero; its.it_interval = zero; timer_settime(lt->timer, 0, &its, NULL); if (lt->cbdata.type == LUASANDBOX_TIMER_PROFILER) { // Invalidate the cbdata, delete the timer lt->cbdata.sandbox = NULL; timer_delete(lt->timer); // If the timer event handler is running, wait for it to finish // before returning to the caller, otherwise the timer event handler // may find itself with a dangling pointer in its local scope. while (sem_wait(<->cbdata.semaphore) && errno == EINTR); sem_destroy(<->cbdata.semaphore); } else { // Block the signal, delete the timer, flush pending signals, restore sigset_t sigset, oldset, pendset; siginfo_t info; sigemptyset(&sigset); sigaddset(&sigset, LUASANDBOX_SIGNAL); sigprocmask(SIG_BLOCK, &sigset, &oldset); timer_delete(lt->timer); while (1) { sigpending(&pendset); if (!sigismember(&pendset, LUASANDBOX_SIGNAL)) { break; } sigwaitinfo(&sigset, &info); luasandbox_timer_handle_signal(LUASANDBOX_SIGNAL, &info, NULL); } sigprocmask(SIG_SETMASK, &oldset, NULL); } }
static int trv_joystick_wait(void) { sigset_t set; struct siginfo value; int ret; /* Wait for a signal */ (void)sigemptyset(&set); (void)sigaddset(&set, CONFIG_GRAPHICS_TRAVELER_JOYSTICK_SIGNO); ret = sigwaitinfo(&set, &value); if (ret < 0) { int errcode = errno; fprintf(stderr, "ERROR: sigwaitinfo() failed: %d\n", errcode); return -errcode; } return OK; }
/** * This is a thread with priority kernel_prio that synchronously waits for * rtdal_pipeline signals (usign sigwaitinfo). All signals except thread-specific * ones (SIGSEGV,SIGILL,SIGBUS,SIGFPE) are blocked by all threads except this one. * Thread-specific signals are handled by ProcThreads which send a SIGRTMIN+1, * SIGRTMIN+2,SIGRTMIN+3,SIGRTMIN+4 (respectively) to this thread, which takes * actions accordingly. * * for signals SIGRTMIN to SIGRTMIN+4, cast the rtdal_pipeline object from this * si_value pointer and call rtdal_pipeline_recover_thread(pipeline, * pipeline->running_process, TRUE) */ void sigwait_loop(void) { int signum; sigset_t set; siginfo_t info; sigfillset(&set); sigdelset(&set,TASK_TERMINATION_SIGNAL); while(!sigwait_stops) { do { signum = sigwaitinfo(&set, &info); } while (signum == -1 && errno == EINTR); if (signum == -1) { poserror(errno, "sigwaitinfo"); goto out; } hdebug("detected signal %d\n",signum); if (signum == KERNEL_SIG_THREAD_SPECIFIC) { printf("[rtdal]: Caught thread-specific signal\n"); #ifdef EXIT_ON_THREADSIG fflush(stdout); goto out; #else sigwait_loop_process_thread_signal(&info); #endif } else if (signum == SIGINT) { printf("Caught SIGINT, exiting\n"); fflush(stdout); goto out; } else if (signum != SIGWINCH && signum != SIGCHLD) { printf("Got signal %d, exiting\n", signum); fflush(stdout); goto out; } } out: kernel_exit(); }
static int lio_waitall(FAR struct aiocb *const *list, int nent) { sigset_t set; int ret; /* Loop until all I/O completes */ for (;;) { /* Check if all I/O has completed */ ret = lio_checkio(list, nent); if (ret != -EINPROGRESS) { /* All I/O has completed.. We are finished. */ return ret; } /* Then wait for SIGPOLL -- indefinitely. * * NOTE: If completion of the I/O causes other signals to be generated * first, then this will wake up and return EINTR instead of success. */ sigemptyset(&set); sigaddset(&set, SIGPOLL); ret = sigwaitinfo(&set, NULL); if (ret < 0) { /* The most likely reason that we would get here is because some * unrelated signal has been received. */ int errcode = get_errno(); fdbg("ERROR: sigwaitinfo failed: %d\n", errcode); DEBUGASSERT(errcode > 0); return -errcode; } } }
void signal_check_functions(pthread_t tid, sigset_t *ss, union sigval sv) { typedef void (*signal_cb_t)(int ); (void)kill((pid_t)0, 0); #if __XSI_VISIBLE (void)killpg((pid_t)0, 0); #endif #if !__APPLE__ (void)psiginfo((const siginfo_t *)0, (const char *)0); #endif (void)psignal(0, (const char*)0); (void)pthread_kill(tid, 0); (void)pthread_sigmask(0, (const sigset_t*)0, (sigset_t*)0); (void)raise(0); (void)sigaction(0, (const struct sigaction*)0, (struct sigaction*)0); (void)sigaddset(ss, 0); #if __XSI_VISIBLE (void)sigaltstack((const stack_t*)0, (stack_t*)0); #endif (void)sigdelset(ss, 0); (void)sigemptyset(ss); (void)sigfillset(ss); (void)sigismember(ss, 0); (void)signal(0, (signal_cb_t)0); (void)sigpending(ss); (void)sigprocmask(0, (const sigset_t*)0, (sigset_t*)0); #if _POSIX_REALTIME_SIGNALS > 0 (void)sigqueue((pid_t)0, 0, sv); #endif (void)sigsuspend(ss); #if _POSIX_REALTIME_SIGNALS > 0 (void)sigtimedwait((const sigset_t*)0, (siginfo_t*)0, (const struct timespec*)0); #endif (void)sigwait(ss, (int*)0); #if _POSIX_REALTIME_SIGNALS > 0 (void)sigwaitinfo(ss, (siginfo_t*)0); #endif }
/* Helper function to support starting threads for SIGEV_THREAD. */ static void *timer_thread_main (void *arg) { /* Wait for the SIGTIMER signal */ sem_t *sem = (sem_t *)arg; #ifdef ANDROID unsigned long sigset[2]; memset(&sigset, 0, sizeof(sigset)); #else sigset_t sigset; sigemptyset(&sigset); #endif sigaddset((sigset_t*)&sigset, SIGTIMER); th_timer_tid = gettid(); sem_post(sem); /* Endless loop for waiting for signals. The loop is only ended when the thread is canceled. */ while (1) { siginfo_t si; int result; #ifdef ANDROID result = __rt_sigtimedwait((sigset_t*)&sigset, &si, NULL, sizeof(sigset)); #else result = sigwaitinfo(&sigset, &si); #endif if (result > 0) { if (si.si_code == SI_TIMER) { timer *t; t = static_cast<timer*>(si.si_value.sival_ptr); t->alarm.signal(); } } } return NULL; }
int main(void) { int pid, rtsig; union sigval value; struct sigaction act; sigset_t selectset; act.sa_flags = SA_SIGINFO; act.sa_sigaction = myhandler; sigemptyset(&act.sa_mask); sigemptyset(&selectset); for (rtsig = SIGRTMAX; rtsig >= SIGRTMIN; rtsig--) { sigaddset(&act.sa_mask, rtsig); sighold(rtsig); sigaddset(&selectset, rtsig); } pid = getpid(); value.sival_int = 5; /* 5 is just an arbitrary value */ for (rtsig = SIGRTMAX; rtsig >= SIGRTMIN; rtsig--) { sigaction(rtsig, &act, 0); if (sigqueue(pid, rtsig, value) != 0) { printf ("Test UNRESOLVED: call to sigqueue did not return success\n"); return PTS_UNRESOLVED; } } if (sigwaitinfo(&selectset, NULL) != SIGRTMIN) { printf ("Test FAILED: sigwaitinfo() did not return the lowest of the multiple pending signals between SIGRTMIN and SIGRTMAX\n"); return PTS_FAIL; } return PTS_PASS; }
static void * timer_notify_thread_func(void *arg) { sigset_t set; siginfo_t info; my_timer_t *timer; pthread_barrier_t *barrier= arg; my_thread_init(); sigemptyset(&set); sigaddset(&set, MY_TIMER_EVENT_SIGNO); sigaddset(&set, MY_TIMER_KILL_SIGNO); /* Get the thread ID of the current thread. */ timer_notify_thread_id= (pid_t) syscall(SYS_gettid); /* Wake up parent thread, timer_notify_thread_id is available. */ pthread_barrier_wait(barrier); while (1) { if (sigwaitinfo(&set, &info) < 0) continue; if (info.si_signo == MY_TIMER_EVENT_SIGNO) { timer= (my_timer_t*)info.si_value.sival_ptr; timer->notify_function(timer); } else if (info.si_signo == MY_TIMER_KILL_SIGNO) break; } my_thread_end(); return NULL; }
void* sigmgr_thread() { sigset_t waitset, oset; siginfo_t info; int rc; pthread_t ppid = pthread_self(); pthread_detach(ppid); sigemptyset(&waitset); sigaddset(&waitset, SIGRTMIN); sigaddset(&waitset, SIGUSR1); while (1) { rc = sigwaitinfo(&waitset, &info); if (rc != -1) { printf("sigwaitinfo() fetch the signal - %d\n", rc); sig_handler(info.si_signo); } else { printf("sigwaitinfo() returned err: %d; %s\n", errno, strerror(errno)); } } }
TEST(signal, sigwaitinfo) { // Block SIGALRM. sigset_t just_SIGALRM; sigemptyset(&just_SIGALRM); sigaddset(&just_SIGALRM, SIGALRM); sigset_t original_set; ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set)); // Raise SIGALRM. sigval_t sigval; sigval.sival_int = 1; ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval)); // Get pending SIGALRM. siginfo_t info; errno = 0; ASSERT_EQ(SIGALRM, sigwaitinfo(&just_SIGALRM, &info)); ASSERT_EQ(0, errno); ASSERT_EQ(SIGALRM, info.si_signo); ASSERT_EQ(1, info.si_value.sival_int); ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL)); }
int ping_via_slots(const char *name, struct servants_list_item *servants) { int sig = 0; pid_t pid = 0; int status = 0; int servants_finished = 0; sigset_t procmask; siginfo_t sinfo; struct servants_list_item *s; sigemptyset(&procmask); sigaddset(&procmask, SIGCHLD); sigprocmask(SIG_BLOCK, &procmask, NULL); for (s = servants; s; s = s->next) { if(sbd_is_disk(s)) { s->pid = assign_servant(s->devname, &slot_ping_wrapper, 0, (const void*)name); } } while (servants_finished < disk_count) { sig = sigwaitinfo(&procmask, &sinfo); if (sig == SIGCHLD) { while ((pid = wait(&status))) { if (pid == -1 && errno == ECHILD) { break; } else { s = lookup_servant_by_pid(pid); if (s && sbd_is_disk(s)) { servants_finished++; } } } } } return 0; }
/*[sig_thread]*/ static void *sig_thread(void *arg) { int signum; siginfo_t info; do { signum = sigwaitinfo((sigset_t *)arg, &info); if (signum == MYSIG_COUNT) printf("Got MYSIG_COUNT; value: %s\n", (char *)info.si_value.sival_ptr); else if (signum == MYSIG_STOP) { printf("Got MYSIG_STOP; terminating thread\n"); return (void *)true; } else printf("Got %d\n", signum); } while (signum != -1 || errno == EINTR); EC_FAIL EC_CLEANUP_BGN EC_FLUSH("sig_thread") return (void *)false; EC_CLEANUP_END }
/** * 功能: 专职信号处理线程 * 说明: * 1.将别的线程阻塞起来的信号,全部加入到自己的监听掩码中来 * 2.无限循环,阻塞起来,等待自己监听的信号到来 * 注意: * 1. 对于共有信号的这种处理,是"同步"方式 * 返回:成功:0; 失败:-x **/ static void* msd_signal_thread_cycle(void *arg) { sigset_t waitset; siginfo_t info; int rc; msd_thread_signal_t *sig_worker = (msd_thread_signal_t *)arg; MSD_INFO_LOG("Worker[Signal] begin to work"); /* 将别的线程阻塞的信号,全部加入自己的监听范围 */ sigemptyset(&waitset); sigaddset(&waitset, SIGTERM); sigaddset(&waitset, SIGQUIT); sigaddset(&waitset, SIGCHLD); sigaddset(&waitset, SIGPIPE); sigaddset(&waitset, SIGINT); sigaddset(&waitset, SIGHUP); /* 无线循环阻塞,等待信号到来 */ while (1) { rc = sigwaitinfo(&waitset, &info); if (rc != MSD_ERR) { /* 同步处理信号 */ msd_public_signal_handler(info.si_signo, sig_worker); } else { MSD_ERROR_LOG("Sigwaitinfo() returned err: %d; %s", errno, strerror(errno)); } } //free(sig_worker);//msd_destroy_instance中会统一释放资源 return (void *)NULL; }
void runFailure1() { sigwaitinfo(anyset(), NULL); }
void runFailure() { sigwaitinfo(NULL, anyinfo()); }
void runSuccess() { sigwaitinfo(anyset(), anyinfo()); }
static int my_sigwaitinfo(const sigset_t* set, siginfo_t* info, struct timespec* timeout) { return sigwaitinfo(set, info); }
int main(void) { int status; struct mq_attr attr; struct sigaction sa; sigset_t set; siginfo_t info; mqd_t mq; pid_t pid; PLAIN_REQUIRE_KERNEL_MODULE("mqueuefs", 0); mq_unlink(MQNAME); sigemptyset(&set); sigaddset(&set, SIGRTMIN); sigprocmask(SIG_BLOCK, &set, NULL); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = (void *) SIG_DFL; sigaction(SIGRTMIN, &sa, NULL); attr.mq_maxmsg = 5; attr.mq_msgsize = 128; mq = mq_open(MQNAME, O_CREAT | O_RDWR | O_EXCL, 0666, &attr); if (mq == (mqd_t)-1) err(1, "mq_open()"); status = mq_getattr(mq, &attr); if (status) err(1, "mq_getattr()"); pid = fork(); if (pid == 0) { /* child */ int prio, j, i; char *buf; struct sigevent sigev; signal(SIGALRM, sighandler); sigev.sigev_notify = SIGEV_SIGNAL; sigev.sigev_signo = SIGRTMIN; sigev.sigev_value.sival_int = 2; mq_close(mq); mq = mq_open(MQNAME, O_RDWR | O_NONBLOCK); if (mq == (mqd_t)-1) err(1, "child: mq_open"); buf = malloc(attr.mq_msgsize); for (j = 0; j < LOOPS; ++j) { alarm(3); status = mq_notify(mq, &sigev); if (status) err(1, "child: mq_notify"); status = sigwaitinfo(&set, &info); if (status == -1) err(1, "child: sigwaitinfo"); if (info.si_value.sival_int != 2) err(1, "child: sival_int"); status = mq_receive(mq, buf, attr.mq_msgsize, &prio); if (status == -1) err(2, "child: mq_receive"); for (i = 0; i < attr.mq_msgsize; ++i) if (buf[i] != i) err(3, "child: message data corrupted"); if (prio != PRIO) err(4, "child: priority is incorrect: %d", prio); } alarm(0); free(buf); mq_close(mq); return (0); } else if (pid == -1) { err(1, "fork()"); } else { char *buf; int i, j; signal(SIGALRM, sighandler); buf = malloc(attr.mq_msgsize); for (j = 0; j < LOOPS; ++j) { for (i = 0; i < attr.mq_msgsize; ++i) { buf[i] = i; } alarm(3); status = mq_send(mq, buf, attr.mq_msgsize, PRIO); if (status) { kill(pid, SIGKILL); err(2, "mq_send()"); } } alarm(3); wait(&status); alarm(0); } status = mq_close(mq); if (status) err(1, "mq_close"); mq_unlink(MQNAME); return (0); }
static void pcntl_sigwaitinfo(INTERNAL_FUNCTION_PARAMETERS, int timedwait) /* {{{ */ { zval *user_set, **user_signo, *user_siginfo = NULL; long tv_sec = 0, tv_nsec = 0; sigset_t set; HashPosition pos; int signo; siginfo_t siginfo; struct timespec timeout; if (timedwait) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zll", &user_set, &user_siginfo, &tv_sec, &tv_nsec) == FAILURE) { return; } } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|z", &user_set, &user_siginfo) == FAILURE) { return; } } if (sigemptyset(&set) != 0) { PCNTL_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); RETURN_FALSE; } zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(user_set), &pos); while (zend_hash_get_current_data_ex(Z_ARRVAL_P(user_set), (void **)&user_signo, &pos) == SUCCESS) { if (Z_TYPE_PP(user_signo) != IS_LONG) { SEPARATE_ZVAL(user_signo); convert_to_long_ex(user_signo); } signo = Z_LVAL_PP(user_signo); if (sigaddset(&set, signo) != 0) { PCNTL_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); RETURN_FALSE; } zend_hash_move_forward_ex(Z_ARRVAL_P(user_set), &pos); } if (timedwait) { timeout.tv_sec = (time_t) tv_sec; timeout.tv_nsec = tv_nsec; signo = sigtimedwait(&set, &siginfo, &timeout); } else { signo = sigwaitinfo(&set, &siginfo); } if (signo == -1 && errno != EAGAIN) { PCNTL_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", strerror(errno)); } /* * sigtimedwait and sigwaitinfo can return 0 on success on some * platforms, e.g. NetBSD */ if (!signo && siginfo.si_signo) { signo = siginfo.si_signo; } if (signo > 0 && user_siginfo) { if (Z_TYPE_P(user_siginfo) != IS_ARRAY) { zval_dtor(user_siginfo); array_init(user_siginfo); } else { zend_hash_clean(Z_ARRVAL_P(user_siginfo)); } add_assoc_long_ex(user_siginfo, "signo", sizeof("signo"), siginfo.si_signo); add_assoc_long_ex(user_siginfo, "errno", sizeof("errno"), siginfo.si_errno); add_assoc_long_ex(user_siginfo, "code", sizeof("code"), siginfo.si_code); switch(signo) { #ifdef SIGCHLD case SIGCHLD: add_assoc_long_ex(user_siginfo, "status", sizeof("status"), siginfo.si_status); # ifdef si_utime add_assoc_double_ex(user_siginfo, "utime", sizeof("utime"), siginfo.si_utime); # endif # ifdef si_stime add_assoc_double_ex(user_siginfo, "stime", sizeof("stime"), siginfo.si_stime); # endif add_assoc_long_ex(user_siginfo, "pid", sizeof("pid"), siginfo.si_pid); add_assoc_long_ex(user_siginfo, "uid", sizeof("uid"), siginfo.si_uid); break; #endif case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: add_assoc_double_ex(user_siginfo, "addr", sizeof("addr"), (long)siginfo.si_addr); break; #ifdef SIGPOLL case SIGPOLL: add_assoc_long_ex(user_siginfo, "band", sizeof("band"), siginfo.si_band); # ifdef si_fd add_assoc_long_ex(user_siginfo, "fd", sizeof("fd"), siginfo.si_fd); # endif break; #endif EMPTY_SWITCH_DEFAULT_CASE(); } } RETURN_LONG(signo); }
int main(int argc, char **argv) { (void)argc; (void)argv; int fd = hcall_init(); uval laddr = mem_hold(4096); char *ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, laddr); args.opcode = H_CREATE_MSGQ; args.args[0] = laddr; args.args[1] = 4096; args.args[2] = 0; hcall(&args); uval xirr = args.args[0]; printf(UVAL_CHOOSE("hcall: %x (%lx) %x %x\n", "hcall: %lx (%lx) %lx %lx\n"), args.retval, xirr, args.args[1], args.args[2]); sigfillset(&msg_sig.sa_mask); sigaction(SIGRTMIN, &msg_sig, NULL); ora.oh_interrupt = xirr; ora.oh_signal = SIGRTMIN; ioctl(fd, OH_IRQ_REFLECT, &ora); struct msg_queue *mq = (struct msg_queue *)ptr; printf(UVAL_CHOOSE("msgq: %lx %lx %lx\n", "msgq: %lx %lx %lx\n"), mq->bufSize, mq->head, mq->tail); uval lpid; args.opcode = H_GET_LPID; hcall(&args); lpid = args.args[0]; printf(UVAL_CHOOSE("self lpid: %lx\n", "self lpid: %lx\n"), lpid); while (1) { sigset_t set; sigemptyset(&set); sigaddset(&set, SIGRTMIN); siginfo_t info; int ret = sigwaitinfo(&set, &info); printf("sigwaitinfo: %d\n", ret); printf(UVAL_CHOOSE("msgq: %lx %lx %lx\n", "msgq: %lx %lx %lx\n"), mq->bufSize, mq->head, mq->tail); int tail = mq->tail % mq->bufSize; struct async_msg_s *msg = &mq->buffer[tail]; printf(UVAL_CHOOSE("msg from: %lx\n", "msg from: %lx\n"), msg->am_source); printf(UVAL_CHOOSE("msg raw data: %lx %lx %lx %lx\n", "msg raw data: %lx %lx %lx %lx\n"), msg->am_data.amu_data[0], msg->am_data.amu_data[1], msg->am_data.amu_data[2], msg->am_data.amu_data[3]); ++mq->tail; } close(fd); return 0; }
/** * int main() * * Invokes the backend, waits until it has successfully detached from the I/O ports, * and then quits. */ int main() { /** Block SIGUSR1, SIGCHLD until we can handle them. */ sigset_t waitset; sigemptyset(&waitset); sigaddset(&waitset, SIGUSR1); sigaddset(&waitset, SIGCHLD); sigprocmask(SIG_BLOCK, &waitset, NULL); /** Install signal handlers for those signals. */ struct sigaction actions; sigemptyset(&actions.sa_mask); actions.sa_flags = SA_SIGINFO; actions.sa_sigaction = dummy_signal_action; sigaction(SIGUSR1, &actions, NULL); sigaction(SIGCHLD, &actions, NULL); /** Fork the child */ pid_t childpid = fork(); if(childpid < 0) { perror("Could not fork() child:"); return 1; } if(childpid == 0) { /* Detach session, setup file descriptors, spawn Racket process. */ if(setsid() < 0) { perror("Could not detach session:"); return 1; } #ifndef NDEBUG putenv("PLTSTDERR=debug"); #endif // Prefer build directory if debug build. if(!IS_INSTALLED() && access(SEASHELL_DEBUG_MAIN, F_OK) != -1) { char * argv2[] = {SEASHELL_DEBUG_MAIN, "-s", NULL}; execv(SEASHELL_DEBUG_MAIN, argv2); perror("Could not execv() the Seashell backend:"); return 1; } // Main case if not in debug mode (fall through if) char * argv[] = {SEASHELL_MAIN, "-s", NULL}; execv(SEASHELL_MAIN, argv); perror("Could not execv() the Seashell backend:"); return 1; } else { /* Setup file descriptors, pass key and port, exit. */ while (true) { siginfo_t info; int result = sigwaitinfo(&waitset, &info); if (result < 0) { if (errno == EINTR) { continue; } else { perror("sigwaitinfo failed with:"); return 1; } } else { /** Wait for the process to quit (successfully) or detach. */ if (info.si_signo == SIGCHLD) { int status = 0; result = waitpid(childpid, &status, WCONTINUED | WUNTRACED); if (result < 0) { perror("wait failed with:"); return 1; } else if (WIFEXITED(status)) { return WEXITSTATUS(status); } } else if (info.si_signo == SIGUSR1) { return 0; } } } } }
static ptid_t nto_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int target_options) { sigset_t set; siginfo_t info; procfs_status status; const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY); TRACE ("%s\n", __func__); ourstatus->kind = TARGET_WAITKIND_SPURIOUS; sigemptyset (&set); sigaddset (&set, SIGUSR1); devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0); while (!(status.flags & _DEBUG_FLAG_ISTOP)) { sigwaitinfo (&set, &info); devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0); } nto_find_new_threads (&nto_inferior); if (status.flags & _DEBUG_FLAG_SSTEP) { TRACE ("SSTEP\n"); ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->value.sig = TARGET_SIGNAL_TRAP; } /* Was it a breakpoint? */ else if (status.flags & trace_mask) { TRACE ("STOPPED\n"); ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->value.sig = TARGET_SIGNAL_TRAP; } else if (status.flags & _DEBUG_FLAG_ISTOP) { TRACE ("ISTOP\n"); switch (status.why) { case _DEBUG_WHY_SIGNALLED: TRACE (" SIGNALLED\n"); ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->value.sig = target_signal_from_host (status.info.si_signo); nto_inferior.exit_signo = ourstatus->value.sig; break; case _DEBUG_WHY_FAULTED: TRACE (" FAULTED\n"); ourstatus->kind = TARGET_WAITKIND_STOPPED; if (status.info.si_signo == SIGTRAP) { ourstatus->value.sig = 0; nto_inferior.exit_signo = 0; } else { ourstatus->value.sig = target_signal_from_host (status.info.si_signo); nto_inferior.exit_signo = ourstatus->value.sig; } break; case _DEBUG_WHY_TERMINATED: { int waitval = 0; TRACE (" TERMINATED\n"); waitpid (ptid_get_pid (ptid), &waitval, WNOHANG); if (nto_inferior.exit_signo) { /* Abnormal death. */ ourstatus->kind = TARGET_WAITKIND_SIGNALLED; ourstatus->value.sig = nto_inferior.exit_signo; } else { /* Normal death. */ ourstatus->kind = TARGET_WAITKIND_EXITED; ourstatus->value.integer = WEXITSTATUS (waitval); } nto_inferior.exit_signo = 0; break; } case _DEBUG_WHY_REQUESTED: TRACE ("REQUESTED\n"); /* We are assuming a requested stop is due to a SIGINT. */ ourstatus->kind = TARGET_WAITKIND_STOPPED; ourstatus->value.sig = TARGET_SIGNAL_INT; nto_inferior.exit_signo = 0; break; } } return ptid_build (status.pid, status.tid, 0); }
void slow_timer_main() { int n; ticks_t ret; struct timer_ln* tl; unsigned short i; #ifdef USE_SIGWAIT int sig; #endif in_slow_timer=1; /* mark this process as the slow timer */ while(1){ #ifdef USE_SIGWAIT n=sigwait(&slow_timer_sset, &sig); #else n=sigwaitinfo(&slow_timer_sset, 0); #endif if (n==-1){ if (errno==EINTR) continue; /* some other signal, ignore it */ LM_ERR("sigwaitinfo failed: %s [%d]\n", strerror(errno), errno); sleep(1); /* try to continue */ } #ifdef USE_SIGWAIT if (sig!=SLOW_TIMER_SIG){ #ifdef __OS_darwin /* on darwin sigwait is buggy: it will cause extreme slow down * on signal delivery for the signals it doesn't wait on * (on darwin 8.8.0, g4 1.5Ghz I've measured a 36s delay!). * To work arround this bug, we sigwait() on all the signals we * are interested in ser and manually call the master signal handler * if the signal!= slow timer signal -- andrei */ sig_usr(sig); #endif continue; } #endif /* update the local cfg if needed */ cfg_update(); LOCK_SLOW_TIMER_LIST(); while(*s_idx!=*t_idx){ i= *s_idx%SLOW_LISTS_NO; while(slow_timer_lists[i].next!= (struct timer_ln*)&slow_timer_lists[i]){ tl=slow_timer_lists[i].next; _timer_rm_list(tl); tl->next=tl->prev=0; #ifdef TIMER_DEBUG tl->expires_no++; #endif SET_RUNNING_SLOW(tl); UNLOCK_SLOW_TIMER_LIST(); ret=tl->f(*ticks, tl, tl->data); /* reset the configuration group handles */ cfg_reset_all(); if (ret==0){ /* one shot */ UNSET_RUNNING_SLOW(); LOCK_SLOW_TIMER_LIST(); }else{ /* not one shot, re-add it */ LOCK_TIMER_LIST(); /* add it to the "main" list */ RESET_SLOW_LIST(tl); if (ret!=(ticks_t)-1) /* != periodic */ tl->initial_timeout=ret; _timer_add(*ticks, tl); UNLOCK_TIMER_LIST(); LOCK_SLOW_TIMER_LIST(); UNSET_RUNNING_SLOW(); } } (*s_idx)++; } UNLOCK_SLOW_TIMER_LIST(); } }
int main(int argc, char *argv[]) { struct sigevent sev; mqd_t mqd; struct mq_attr attr; void *buffer; ssize_t numRead; sigset_t blockMask; siginfo_t si; if (argc != 2 || strcmp(argv[1], "--help") == 0) usageErr("%s mq-name\n", argv[0]); mqd = mq_open(argv[1], O_RDONLY | O_NONBLOCK); if (mqd == (mqd_t) -1) errExit("mq_open"); /* Determine mq_msgsize for message queue, and allocate an input buffer of that size */ if (mq_getattr(mqd, &attr) == -1) errExit("mq_getattr"); buffer = malloc(attr.mq_msgsize); if (buffer == NULL) errExit("malloc"); /* Block the signal that we'll accept using sigwaitinfo() */ sigemptyset(&blockMask); sigaddset(&blockMask, NOTIFY_SIG); if (sigprocmask(SIG_BLOCK, &blockMask, NULL) == -1) errExit("sigprocmask"); /* Set up message notification using the signal NOTIFY_SIG */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = NOTIFY_SIG; sev.sigev_value.sival_ptr = &mqd; /* This allows us to obtain a pointer to 'mqd' in the siginfo_t structure returned by sigwaitinfo() */ if (mq_notify(mqd, &sev) == -1) errExit("mq_notify"); for (;;) { /* Wait for a signal; when it is received, display associated information */ if (sigwaitinfo(&blockMask, &si) == -1) errExit("sigwaitinfo"); printf("Accepted signal:\n"); printf(" si_signo = %d\n", si.si_signo); printf(" si_pid = %ld\n", (long) si.si_pid); printf(" si_uid = %ld\n", (long) si.si_uid); printf(" si_code = %d (%s)\n", si.si_code, (si.si_code == SI_MESGQ) ? "SI_MESGQ" : "???"); printf(" *sival_ptr = %p\n\n", si.si_value.sival_ptr); /* Reestablish message notification */ if (mq_notify(mqd, &sev) == -1) errExit("mq_notify"); /* Although only one signal might have been queued (if NOTIFY_SIG is a standard signal) we might have received multiple messages, so use nonblocking mq_receive() calls inside a loop to read as many messages as possible. */ while ((numRead = mq_receive(mqd, buffer, attr.mq_msgsize, NULL)) >= 0) printf("Read %ld bytes\n", (long) numRead); if (errno != EAGAIN) /* Unexpected error */ errExit("mq_receive"); } }
int waitid(idtype_t idtype, id_t id, siginfo_t *info, int options) { FAR _TCB *rtcb = (FAR _TCB *)g_readytorun.head; sigset_t sigset; int err; int ret; /* MISSING LOGIC: If WNOHANG is provided in the options, then this function * should returned immediately. However, there is no mechanism available now * know if the thread has child: The children remember their parents (if * CONFIG_SCHED_HAVE_PARENT) but the parents do not remember their children. */ /* None of the options are supported except for WEXITED (which must be * provided. Currently SIGCHILD always reports CLD_EXITED so we cannot * distinguish any other events. */ #ifdef CONFIG_DEBUG if (options != WEXITED) { set_errno(ENOSYS); return ERROR; } #endif /* Create a signal set that contains only SIGCHLD */ (void)sigemptyset(&sigset); (void)sigaddset(&sigset, SIGCHLD); /* Disable pre-emption so that nothing changes while the loop executes */ sched_lock(); /* Verify that this task actually has children and that the the requeste * TCB is actually a child of this task. */ if (rtcb->nchildren == 0) { err = ECHILD; goto errout_with_errno; } else if (idtype == P_PID) { /* Get the TCB corresponding to this PID and make sure it is our child. */ FAR _TCB *ctcb = sched_gettcb((pid_t)id); if (!ctcb || ctcb->parent != rtcb->pid) { err = ECHILD; goto errout_with_errno; } } /* Loop until the child that we are waiting for dies */ for (;;) { /* Check if the task has already died. Signals are not queued in * NuttX. So a possibility is that the child has died and we * missed the death of child signal (we got some other signal * instead). */ if (rtcb->nchildren == 0 || (idtype == P_PID && (ret = kill((pid_t)id, 0)) < 0)) { /* We know that the child task was running okay we stared, * so we must have lost the signal. What can we do? * Let's claim we were interrupted by a signal. */ err = EINTR; goto errout_with_errno; } /* Wait for any death-of-child signal */ ret = sigwaitinfo(&sigset, info); if (ret < 0) { goto errout; } /* Make there this was SIGCHLD */ if (info->si_signo == SIGCHLD) { /* Yes.. Are we waiting for the death of a specific child? */ if (idtype == P_PID) { /* Was this the death of the thread we were waiting for? */ if (info->si_pid == (pid_t)id) { /* Yes... return success */ break; } } /* Are we waiting for any child to change state? */ else if (idtype == P_ALL) { /* Return success */ break; } /* Other ID types are not supported */ else /* if (idtype == P_PGID) */ { set_errno(ENOSYS); goto errout; } } } sched_unlock(); return OK; errout_with_errno: set_errno(err); errout: sched_unlock(); return ERROR; }
//следим за потомком int TDaemon::MonitorProc() { int pid; int status; int need_start = 1; sigset_t sigset; siginfo_t siginfo; // настраиваем сигналы которые будем обрабатывать sigemptyset(&sigset); // сигнал остановки процесса пользователем sigaddset(&sigset, SIGQUIT); // сигнал для остановки процесса пользователем с терминала sigaddset(&sigset, SIGINT); // сигнал запроса завершения процесса sigaddset(&sigset, SIGTERM); // сигнал посылаемый при изменении статуса дочернего процесса sigaddset(&sigset, SIGCHLD); // пользовательский сигнал который мы будем использовать для обновления конфига sigaddset(&sigset, SIGHUP); sigprocmask(SIG_BLOCK, &sigset, NULL); // данная функция создаст файл с нашим PID'ом SetPidFile(PID_FILE.c_str()); // бесконечный цикл работы for (;;) { // если необходимо создать потомка if (need_start) { // создаём потомка pid = fork(); } need_start = 1; if (pid == -1) // если произошла ошибка { // запишем в лог сообщение об этом WriteLog("%s [MONITOR] Fork failed (%s)\n",getTime(), strerror(errno)); } else if (!pid) // если мы потомок { // данный код выполняется в потомке // запустим функцию отвечающую за работу демона status = WorkProc(); // завершим процесс exit(status); } else // если мы родитель { // данный код выполняется в родителе // ожидаем поступление сигнала sigwaitinfo(&sigset, &siginfo); // если пришел сигнал от потомка if (siginfo.si_signo == SIGCHLD) { // получаем статус завершение wait(&status); // преобразуем статус в нормальный вид status = WEXITSTATUS(status); // если потомок завершил работу с кодом говорящем о том, что нет нужды дальше работать if (status == CHILD_NEED_TERMINATE) { // запишем в лог сообщени об этом WriteLog("%s [MONITOR] Child stopped\n", getTime()); // прервем цикл break; } else if (status == CHILD_NEED_WORK) // если требуется перезапустить потомка { // запишем в лог данное событие WriteLog("%s [MONITOR] Child restart\n", getTime()); } } else if (siginfo.si_signo == SIGHUP) // если пришел сигнал что необходимо перезагрузить конфиг { kill(pid, SIGHUP); // перешлем его потомку need_start = 0; // установим флаг что нам не надо запускать потомка заново } else // если пришел какой-либо другой ожидаемый сигнал { // запишем в лог информацию о пришедшем сигнале WriteLog("%s [MONITOR] Signal %s\n", getTime(), strsignal(siginfo.si_signo)); // убьем потомка kill(pid, SIGTERM); status = 0; break; } } } // запишем в лог, что мы остановились WriteLog("%s [MONITOR] Stop\n", getTime()); // удалим файл с PID'ом unlink(PID_FILE.c_str()); return status; }
main (int argc, char **argv) { struct sigaction sa; timer_t my_alarm; struct sigevent sigspec; union sigval value; int status; sigset_t sigset; if (argc < 2) { printf("syntax : ex2 measure_time [sec]\n"); exit(1); } // Défini le moment en seconde où le timer terminera. // Pas d'intervalle définit donc il déclenche une seule fois. setting.it_value.tv_sec = atoi(argv[1]); setting.it_value.tv_nsec = 0; setting.it_interval.tv_sec = 0; setting.it_interval.tv_nsec = 0; // action signal info et définition de la fonction fin comme action // SIGINFO signifie que des signaux POSIX4 ŝont attendus sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = fin; // Sigaction change sa pour le signal de timer if (sigaction(MYSIGALARM, &sa, NULL) < 0) { perror("sigaction MYSIGALARM"); exit(1); } // On définit ici quel type de signal est attendu sigspec.sigev_signo = MYSIGALARM; sigspec.sigev_notify = SIGEV_SIGNAL; sigspec.sigev_value.sival_int = 1; // on crée notre timer, qui n'est pas encore déclenché ici. // Son pointeur est enregistré dans my_alarm. // CLOCK_REALTIME est l'horloge système. // sigspec est ici l'événement à envoyer quand le timer termine le décompte. if (timer_create(CLOCK_REALTIME, &sigspec, &my_alarm) != 0) { perror("timer_create"); exit(1); } // On lance le timer avec les paramètres définis précédemment if (timer_settime(my_alarm, 0, &setting, NULL) != 0) { perror("timer_settime"); exit(1); } // On vide sigset pour le préparer à recevoir sa nouvelle valeur sigemptyset(&sigset); // On définit sigset avec la valeur SIGRTMAX, la borne max (donc de basse priorité!) sigaddset(&sigset, MYSIGALARM); // On attend que le signal soit déclenché par le timer. Dès qu'il est intercepté, // la fonction se termine status = sigwaitinfo(&sigset, NULL); printf("recu le signal # %d, handler_execute = %d status = %d\n", nb, handler_execute,status); if (status == -1) perror("sigsuspend"); }
void *s_signalListener( void *my_stack ) { static BOOL bFirst = TRUE; sigset_t passall; HB_STACK *pStack = (HB_STACK*) my_stack; #if defined( HB_OS_BSD ) int sig; #else siginfo_t sinfo; #endif #ifdef HB_THREAD_TLS_KEYWORD hb_thread_stack = my_stack; #else pthread_setspecific( hb_pkCurrentStack, my_stack ); #endif pStack->th_id = HB_CURRENT_THREAD(); hb_threadLinkStack( pStack ); HB_STACK_LOCK; // and now accepts all signals sigemptyset( &passall ); // and wait for all signals sigaddset( &passall, SIGHUP ); sigaddset( &passall, SIGQUIT ); sigaddset( &passall, SIGILL ); sigaddset( &passall, SIGABRT ); sigaddset( &passall, SIGFPE ); sigaddset( &passall, SIGSEGV ); sigaddset( &passall, SIGTERM ); sigaddset( &passall, SIGUSR1 ); sigaddset( &passall, SIGUSR2 ); sigaddset( &passall, SIGHUP ); pthread_cleanup_push( hb_threadTerminator, my_stack ); pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL ); pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL ); while ( 1 ) { // allow safe cancelation HB_STACK_UNLOCK; // reset signal handling; this is done here (so I don't // mangle with pthread_ calls, and I don't hold mutexes), // and just once (doing it twice would be useless). if ( bFirst ) { pthread_sigmask( SIG_SETMASK, &passall, NULL ); bFirst = FALSE; } // This is also a cancelation point. When the main thread // is done, it will kill all the threads having a stack // including this one. // ATM we don't care very much about signal handling during // termination: no handler is set for them, so the DFL // action is taken (and that should be fine). #if defined( HB_OS_BSD ) sigwait( &passall, &sig ); #else sigwaitinfo( &passall, &sinfo ); #endif // lock stack before passing the ball to VM. HB_STACK_LOCK; #if defined( HB_OS_BSD ) s_signalHandler( sig, NULL, NULL ); #else s_signalHandler( sinfo.si_signo, &sinfo, NULL ); #endif } pthread_cleanup_pop( 1 ); return 0; }
/** * Run the daemon and handle unix signals */ static int run() { sigset_t set; /* handle SIGINT, SIGHUP and SIGTERM in this handler */ sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGHUP); sigaddset(&set, SIGTERM); sigaddset(&set, SIGUSR1); sigprocmask(SIG_BLOCK, &set, NULL); while (TRUE) { int sig; sig = sigwaitinfo(&set, NULL); if (sig == -1) { if (errno == EINTR) { /* ignore signals we didn't wait for */ continue; } DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno)); return 1; } switch (sig) { case SIGHUP: { DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading " "configuration"); if (lib->settings->load_files(lib->settings, lib->conf, FALSE)) { charon->load_loggers(charon, levels, TRUE); lib->plugins->reload(lib->plugins, NULL); } else { DBG1(DBG_DMN, "reloading config failed, keeping old"); } break; } case SIGINT: { DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down"); charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); return 0; } case SIGTERM: { DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down"); charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); return 0; } case SIGUSR1: { /* an error occurred */ charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); return 1; } } } }