static int recv_fd(int c) { int fd; uint8_t msgbuf[CMSG_SPACE(sizeof(fd))]; struct msghdr msg = { .msg_control = msgbuf, .msg_controllen = sizeof(msgbuf), }; struct cmsghdr *cmsg; struct iovec iov; uint8_t req[1]; ssize_t len; cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); msg.msg_controllen = cmsg->cmsg_len; iov.iov_base = req; iov.iov_len = sizeof(req); msg.msg_iov = &iov; msg.msg_iovlen = 1; len = recvmsg(c, &msg, 0); if (len > 0) { memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); return fd; } return len; } static int net_bridge_run_helper(const char *helper, const char *bridge, Error **errp) { sigset_t oldmask, mask; int pid, status; char *args[5]; char **parg; int sv[2]; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigprocmask(SIG_BLOCK, &mask, &oldmask); if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { error_setg_errno(errp, errno, "socketpair() failed"); return -1; } /* try to launch bridge helper */ pid = fork(); if (pid < 0) { error_setg_errno(errp, errno, "Can't fork bridge helper"); return -1; } if (pid == 0) { int open_max = sysconf(_SC_OPEN_MAX), i; char fd_buf[6+10]; char br_buf[6+IFNAMSIZ] = {0}; char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15]; for (i = 3; i < open_max; i++) { if (i != sv[1]) { close(i); } } snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]); if (strrchr(helper, ' ') || strrchr(helper, '\t')) { /* assume helper is a command */ if (strstr(helper, "--br=") == NULL) { snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); } snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s", helper, "--use-vnet", fd_buf, br_buf); parg = args; *parg++ = (char *)"sh"; *parg++ = (char *)"-c"; *parg++ = helper_cmd; *parg++ = NULL; execv("/bin/sh", args); } else { /* assume helper is just the executable path name */ snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge); parg = args; *parg++ = (char *)helper; *parg++ = (char *)"--use-vnet"; *parg++ = fd_buf; *parg++ = br_buf; *parg++ = NULL; execv(helper, args); } _exit(1); } else { int fd; int saved_errno; close(sv[1]); do { fd = recv_fd(sv[0]); } while (fd == -1 && errno == EINTR); saved_errno = errno; close(sv[0]); while (waitpid(pid, &status, 0) != pid) { /* loop */ } sigprocmask(SIG_SETMASK, &oldmask, NULL); if (fd < 0) { error_setg_errno(errp, saved_errno, "failed to recv file descriptor"); return -1; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { error_setg(errp, "bridge helper failed"); return -1; } return fd; } }
// 主进程的循环 void ngx_master_process_cycle(ngx_cycle_t *cycle) { char *title; u_char *p; size_t size; ngx_int_t i; ngx_uint_t n, sigio; sigset_t set; struct itimerval itv; ngx_uint_t live; ngx_msec_t delay; ngx_listening_t *ls; ngx_core_conf_t *ccf; sigemptyset(&set); sigaddset(&set, SIGCHLD); sigaddset(&set, SIGALRM); sigaddset(&set, SIGIO); sigaddset(&set, SIGINT); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_NOACCEPT_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigprocmask() failed"); } sigemptyset(&set); size = sizeof(master_process); for (i = 0; i < ngx_argc; i++) { size += ngx_strlen(ngx_argv[i]) + 1; } title = ngx_pnalloc(cycle->pool, size); p = ngx_cpymem(title, master_process, sizeof(master_process) - 1); for (i = 0; i < ngx_argc; i++) { *p++ = ' '; p = ngx_cpystrn(p, (u_char *) ngx_argv[i], size); } ngx_setproctitle(title); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_new_binary = 0; delay = 0; sigio = 0; live = 1; for ( ;; ) { if (delay) { if (ngx_sigalrm) { sigio = 0; delay *= 2; ngx_sigalrm = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "termination cycle: %d", delay); itv.it_interval.tv_sec = 0; itv.it_interval.tv_usec = 0; itv.it_value.tv_sec = delay / 1000; itv.it_value.tv_usec = (delay % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "sigsuspend"); sigsuspend(&set); ngx_time_update(); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "wake up, sigio %i", sigio); // ngx_reap为1表示有子进程退出 if (ngx_reap) { ngx_reap = 0; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children"); // 处理退出的子进程,如果异常退出则重启 live = ngx_reap_children(cycle); } // 如果已经没有子进程活着,并且收到了中断或退出信号,则master退出 if (!live && (ngx_terminate || ngx_quit)) { ngx_master_process_exit(cycle); } // 收到了signalint信号 if (ngx_terminate) { // 设置延时 if (delay == 0) { delay = 50; } if (sigio) { sigio--; continue; } sigio = ccf->worker_processes + 2 /* cache processes */; // 延时太大时强制杀死worker,否则发送sigint给worker if (delay > 1000) { ngx_signal_worker_processes(cycle, SIGKILL); } else { ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_TERMINATE_SIGNAL)); } continue; } if (ngx_quit) { // 发送quit信号给所有worker ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); ls = cycle->listening.elts; for (n = 0; n < cycle->listening.nelts; n++) { if (ngx_close_socket(ls[n].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[n].addr_text); } } cycle->listening.nelts = 0; continue; } // 重新配置 if (ngx_reconfigure) { ngx_reconfigure = 0; if (ngx_new_binary) { ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); ngx_noaccepting = 0; continue; } ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reconfiguring"); cycle = ngx_init_cycle(cycle); if (cycle == NULL) { cycle = (ngx_cycle_t *) ngx_cycle; continue; } ngx_cycle = cycle; ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_JUST_RESPAWN); ngx_start_cache_manager_processes(cycle, 1); /* allow new processes to start */ ngx_msleep(100); live = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } if (ngx_restart) { ngx_restart = 0; ngx_start_worker_processes(cycle, ccf->worker_processes, NGX_PROCESS_RESPAWN); ngx_start_cache_manager_processes(cycle, 0); live = 1; } if (ngx_reopen) { ngx_reopen = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs"); ngx_reopen_files(cycle, ccf->user); ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_REOPEN_SIGNAL)); } if (ngx_change_binary) { ngx_change_binary = 0; ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "changing binary"); ngx_new_binary = ngx_exec_new_binary(cycle, ngx_argv); } if (ngx_noaccept) { ngx_noaccept = 0; ngx_noaccepting = 1; ngx_signal_worker_processes(cycle, ngx_signal_value(NGX_SHUTDOWN_SIGNAL)); } } }
void trap_init(void) { uint8_t digest[20]; struct sigaction sa, old; char path[256]; int r; memset(digest, 0, sizeof(digest)); r = readlink("/proc/self/exe", self, sizeof(self) - 1); if(r == -1) self[0] = 0; else self[r] = 0; snprintf(line1, sizeof(line1), "PRG: Showtime (%s) " "[%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x] " "EXE: %s, CWD: %s ", htsversion_full, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], digest[11], digest[12], digest[13], digest[14], digest[15], digest[16], digest[17], digest[18], digest[19], self, getcwd(path, sizeof(path))); dl_iterate_phdr(callback, NULL); memset(&sa, 0, sizeof(sa)); sigset_t m; sigemptyset(&m); sigaddset(&m, SIGSEGV); sigaddset(&m, SIGBUS); sigaddset(&m, SIGILL); sigaddset(&m, SIGABRT); sigaddset(&m, SIGFPE); sa.sa_sigaction = traphandler; sa.sa_flags = SA_SIGINFO | SA_RESETHAND; sigaction(SIGSEGV, &sa, &old); sigaction(SIGBUS, &sa, &old); sigaction(SIGILL, &sa, &old); sigaction(SIGABRT, &sa, &old); sigaction(SIGFPE, &sa, &old); sigprocmask(SIG_UNBLOCK, &m, NULL); }
int qat_engine_init(ENGINE *e) { int instNum, err; CpaStatus status = CPA_STATUS_SUCCESS; CpaBoolean limitDevAccess = CPA_FALSE; int ret_pthread_sigmask; pthread_mutex_lock(&qat_engine_mutex); if(engine_inited) { pthread_mutex_unlock(&qat_engine_mutex); return 1; } DEBUG("QAT Engine initialization:\n"); DEBUG("- External polling: %s\n", enable_external_polling ? "ON": "OFF"); DEBUG("- Inline polling: %s\n", enable_inline_polling ? "ON": "OFF"); DEBUG("- Internal poll interval: %dns\n", qat_poll_interval); DEBUG("- Epoll timeout: %dms\n", qat_epoll_timeout); DEBUG("- Event driven polling mode: %s\n", enable_event_driven_polling ? "ON": "OFF"); DEBUG("- Instance for thread: %s\n", enable_instance_for_thread ? "ON": "OFF"); DEBUG("- Max retry count: %d\n", qat_max_retry_count); CRYPTO_INIT_QAT_LOG(); polling_thread = pthread_self(); if ((err = pthread_key_create(&qatInstanceForThread, NULL)) != 0) { WARN("pthread_key_create failed: %s\n", strerror(err)); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_PTHREAD_CREATE_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); return 0; } #ifndef OPENSSL_ENABLE_QAT_UPSTREAM_DRIVER /* limitDevAccess is passed as an input to icp_sal_userStartMultiProcess(). * However, in upstream driver the value is ignored and read directly from * the configuration file -> No need to parse the file here. */ if (!checkLimitDevAccessValue((int *)&limitDevAccess, ICPConfigSectionName_libcrypto)) { WARN("Could not load driver config file. Assuming LimitDevAccess = 0\n"); } #endif /* Initialise the QAT hardware */ if (CPA_STATUS_SUCCESS != icp_sal_userStartMultiProcess(ICPConfigSectionName_libcrypto, limitDevAccess)) { WARN("icp_sal_userStart failed\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_ICP_SAL_USERSTART_FAIL); pthread_mutex_unlock(&qat_engine_mutex); return 0; } /* Get the number of available instances */ status = cpaCyGetNumInstances(&qat_num_instances); if (CPA_STATUS_SUCCESS != status) { WARN("cpaCyGetNumInstances failed, status=%d\n", status); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_GET_NUM_INSTANCE_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } if (!qat_num_instances) { WARN("No crypto instances found\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_INSTANCE_UNAVAILABLE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } DEBUG("Found %d Cy instances\n", qat_num_instances); /* Allocate memory for the instance handle array */ qat_instance_handles = (CpaInstanceHandle *) OPENSSL_zalloc(((int)qat_num_instances) * sizeof(CpaInstanceHandle)); if (NULL == qat_instance_handles) { WARN("OPENSSL_zalloc() failed for instance handles.\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_INSTANCE_HANDLE_MALLOC_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } /* Get the Cy instances */ status = cpaCyGetInstances(qat_num_instances, qat_instance_handles); if (CPA_STATUS_SUCCESS != status) { WARN("cpaCyGetInstances failed, status=%d\n", status); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_GET_INSTANCE_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } if (!enable_external_polling && !enable_inline_polling) { if (qat_is_event_driven()) { CpaStatus status; int flags; int engine_fd; /* Add the file descriptor to an epoll event list */ internal_efd = epoll_create1(0); if (-1 == internal_efd) { WARN("Error creating epoll fd\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_EPOLL_CREATE_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } for (instNum = 0; instNum < qat_num_instances; instNum++) { /* Get the file descriptor for the instance */ status = icp_sal_CyGetFileDescriptor(qat_instance_handles[instNum], &engine_fd); if (CPA_STATUS_FAIL == status) { WARN("Error getting file descriptor for instance\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_GET_FILE_DESCRIPTOR_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } /* Make the file descriptor non-blocking */ eng_poll_st[instNum].eng_fd = engine_fd; eng_poll_st[instNum].inst_index = instNum; flags = fcntl(engine_fd, F_GETFL, 0); fcntl(engine_fd, F_SETFL, flags | O_NONBLOCK); eng_epoll_events[instNum].data.ptr = &eng_poll_st[instNum]; eng_epoll_events[instNum].events = EPOLLIN | EPOLLET; if (-1 == epoll_ctl(internal_efd, EPOLL_CTL_ADD, engine_fd, &eng_epoll_events[instNum])) { WARN("Error adding fd to epoll\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_EPOLL_CTL_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } } } } /* Set translation function and start each instance */ for (instNum = 0; instNum < qat_num_instances; instNum++) { /* Set the address translation function */ status = cpaCySetAddressTranslation(qat_instance_handles[instNum], virtualToPhysical); if (CPA_STATUS_SUCCESS != status) { WARN("cpaCySetAddressTranslation failed, status=%d\n", status); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_SET_ADDRESS_TRANSLATION_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } /* Start the instances */ status = cpaCyStartInstance(qat_instance_handles[instNum]); if (CPA_STATUS_SUCCESS != status) { WARN("cpaCyStartInstance failed, status=%d\n", status); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_START_INSTANCE_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } instance_started[instNum] = 1; } if (!enable_external_polling && !enable_inline_polling) { if (!qat_is_event_driven()) { sigemptyset(&set); sigaddset(&set, SIGUSR1); ret_pthread_sigmask = pthread_sigmask(SIG_BLOCK, &set, NULL); if (ret_pthread_sigmask != 0) { WARN("pthread_sigmask error\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_POLLING_THREAD_SIGMASK_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } } if (qat_create_thread(&polling_thread, NULL, qat_is_event_driven() ? event_poll_func : timer_poll_func, NULL)) { WARN("Creation of polling thread failed\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_POLLING_THREAD_CREATE_FAILURE); polling_thread = pthread_self(); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } if (qat_adjust_thread_affinity(polling_thread) == 0) { WARN("Setting polling thread affinity failed\n"); QATerr(QAT_F_QAT_ENGINE_INIT, QAT_R_SET_POLLING_THREAD_AFFINITY_FAILURE); pthread_mutex_unlock(&qat_engine_mutex); qat_engine_finish(e); return 0; } if (!qat_is_event_driven()) { while (!cleared_to_start) sleep(1); } } /* Reset curr_inst */ curr_inst = 0; engine_inited = 1; pthread_mutex_unlock(&qat_engine_mutex); return 1; }
void nsProfileLock::FatalSignalHandler(int signo #ifdef SA_SIGINFO , siginfo_t *info, void *context #endif ) { // Remove any locks still held. RemovePidLockFiles(PR_TRUE); // Chain to the old handler, which may exit. struct sigaction *oldact = nsnull; switch (signo) { case SIGHUP: oldact = &SIGHUP_oldact; break; case SIGINT: oldact = &SIGINT_oldact; break; case SIGQUIT: oldact = &SIGQUIT_oldact; break; case SIGILL: oldact = &SIGILL_oldact; break; case SIGABRT: oldact = &SIGABRT_oldact; break; case SIGSEGV: oldact = &SIGSEGV_oldact; break; case SIGTERM: oldact = &SIGTERM_oldact; break; default: NS_NOTREACHED("bad signo"); break; } if (oldact) { if (oldact->sa_handler == SIG_DFL) { // Make sure the default sig handler is executed // We need it to get Mozilla to dump core. sigaction(signo,oldact,NULL); // Now that we've restored the default handler, unmask the // signal and invoke it. sigset_t unblock_sigs; sigemptyset(&unblock_sigs); sigaddset(&unblock_sigs, signo); sigprocmask(SIG_UNBLOCK, &unblock_sigs, NULL); raise(signo); } #ifdef SA_SIGINFO else if (oldact->sa_sigaction && (oldact->sa_flags & SA_SIGINFO) == SA_SIGINFO) { oldact->sa_sigaction(signo, info, context); } #endif else if (oldact->sa_handler && oldact->sa_handler != SIG_IGN) { oldact->sa_handler(signo); } } // Backstop exit call, just in case. _exit(signo); }
void Sigaddset(sigset_t *set, int signum) { if (sigaddset(set, signum) < 0) unix_error("Sigaddset error"); return; }
void ipmi_start_daemon(struct ipmi_intf *intf) { pid_t pid; int fd; #ifdef SIGHUP sigset_t sighup; #endif #ifdef SIGHUP sigemptyset(&sighup); sigaddset(&sighup, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &sighup, NULL) < 0) fprintf(stderr, "ERROR: could not unblock SIGHUP signal\n"); signal(SIGHUP, SIG_IGN); #endif #ifdef SIGTTOU signal(SIGTTOU, SIG_IGN); #endif #ifdef SIGTTIN signal(SIGTTIN, SIG_IGN); #endif #ifdef SIGQUIT signal(SIGQUIT, SIG_IGN); #endif #ifdef SIGTSTP signal(SIGTSTP, SIG_IGN); #endif pid = (pid_t) fork(); if (pid < 0 || pid > 0) exit(0); #if defined(SIGTSTP) && defined(TIOCNOTTY) if (setpgid(0, getpid()) == -1) exit(1); if ((fd = open(_PATH_TTY, O_RDWR)) >= 0) { ioctl(fd, TIOCNOTTY, NULL); close(fd); } #else if (setpgid(0, 0) == -1) exit(1); pid = (pid_t) fork(); if (pid < 0 || pid > 0) exit(0); #endif chdir("/"); umask(0); for (fd=0; fd<64; fd++) { if (fd != intf->fd) close(fd); } fd = open("/dev/null", O_RDWR); assert(0 == fd); dup(fd); dup(fd); }
int main(int argc, char **argv) { int i; sigset_t set; #if ENABLE_LINUXDVB uint32_t adapter_mask; #endif int log_level = LOG_INFO; int log_options = TVHLOG_OPT_MILLIS | TVHLOG_OPT_STDERR | TVHLOG_OPT_SYSLOG; const char *log_debug = NULL, *log_trace = NULL; char buf[512]; main_tid = pthread_self(); /* Setup global mutexes */ pthread_mutex_init(&ffmpeg_lock, NULL); pthread_mutex_init(&fork_lock, NULL); pthread_mutex_init(&global_lock, NULL); pthread_mutex_init(&atomic_lock, NULL); pthread_cond_init(>imer_cond, NULL); /* Defaults */ tvheadend_webui_port = 9981; tvheadend_webroot = NULL; tvheadend_htsp_port = 9982; tvheadend_htsp_port_extra = 0; /* Command line options */ int opt_help = 0, opt_version = 0, opt_fork = 0, opt_firstrun = 0, opt_stderr = 0, opt_syslog = 0, opt_uidebug = 0, opt_abort = 0, opt_noacl = 0, opt_fileline = 0, opt_threadid = 0, opt_ipv6 = 0, opt_tsfile_tuner = 0, opt_dump = 0; const char *opt_config = NULL, *opt_user = NULL, *opt_group = NULL, *opt_logpath = NULL, *opt_log_debug = NULL, *opt_log_trace = NULL, *opt_pidpath = "/var/run/tvheadend.pid", #if ENABLE_LINUXDVB *opt_dvb_adapters = NULL, #endif *opt_bindaddr = NULL, *opt_subscribe = NULL; str_list_t opt_tsfile = { .max = 10, .num = 0, .str = calloc(10, sizeof(char*)) }; cmdline_opt_t cmdline_opts[] = { { 0, NULL, "Generic Options", OPT_BOOL, NULL }, { 'h', "help", "Show this page", OPT_BOOL, &opt_help }, { 'v', "version", "Show version infomation", OPT_BOOL, &opt_version }, { 0, NULL, "Service Configuration", OPT_BOOL, NULL }, { 'c', "config", "Alternate config path", OPT_STR, &opt_config }, { 'f', "fork", "Fork and run as daemon", OPT_BOOL, &opt_fork }, { 'u', "user", "Run as user", OPT_STR, &opt_user }, { 'g', "group", "Run as group", OPT_STR, &opt_group }, { 'p', "pid", "Alternate pid path", OPT_STR, &opt_pidpath }, { 'C', "firstrun", "If no user account exists then create one with\n" "no username and no password. Use with care as\n" "it will allow world-wide administrative access\n" "to your Tvheadend installation until you edit\n" "the access-control from within the Tvheadend UI", OPT_BOOL, &opt_firstrun }, #if ENABLE_LINUXDVB { 'a', "adapters", "Only use specified DVB adapters (comma separated)", OPT_STR, &opt_dvb_adapters }, #endif { 0, NULL, "Server Connectivity", OPT_BOOL, NULL }, { '6', "ipv6", "Listen on IPv6", OPT_BOOL, &opt_ipv6 }, { 'b', "bindaddr", "Specify bind address", OPT_STR, &opt_bindaddr}, { 0, "http_port", "Specify alternative http port", OPT_INT, &tvheadend_webui_port }, { 0, "http_root", "Specify alternative http webroot", OPT_STR, &tvheadend_webroot }, { 0, "htsp_port", "Specify alternative htsp port", OPT_INT, &tvheadend_htsp_port }, { 0, "htsp_port2", "Specify extra htsp port", OPT_INT, &tvheadend_htsp_port_extra }, { 0, NULL, "Debug Options", OPT_BOOL, NULL }, { 'd', "stderr", "Enable debug on stderr", OPT_BOOL, &opt_stderr }, { 's', "syslog", "Enable debug to syslog", OPT_BOOL, &opt_syslog }, { 'l', "logfile", "Enable debug to file", OPT_STR, &opt_logpath }, { 0, "debug", "Enable debug subsystems", OPT_STR, &opt_log_debug }, #if ENABLE_TRACE { 0, "trace", "Enable trace subsystems", OPT_STR, &opt_log_trace }, #endif { 0, "fileline", "Add file and line numbers to debug", OPT_BOOL, &opt_fileline }, { 0, "threadid", "Add the thread ID to debug", OPT_BOOL, &opt_threadid }, { 0, "uidebug", "Enable webUI debug (non-minified JS)", OPT_BOOL, &opt_uidebug }, { 'A', "abort", "Immediately abort", OPT_BOOL, &opt_abort }, { 'D', "dump", "Enable coredumps for daemon", OPT_BOOL, &opt_dump }, { 0, "noacl", "Disable all access control checks", OPT_BOOL, &opt_noacl }, { 'j', "join", "Subscribe to a service permanently", OPT_STR, &opt_subscribe }, { 0, NULL, "TODO: testing", OPT_BOOL, NULL }, { 0, "tsfile_tuners", "Number of tsfile tuners", OPT_INT, &opt_tsfile_tuner }, { 0, "tsfile", "tsfile input (mux file)", OPT_STR_LIST, &opt_tsfile }, }; /* Get current directory */ tvheadend_cwd = dirname(dirname(tvh_strdupa(argv[0]))); /* Set locale */ setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); /* make sure the timezone is set */ tzset(); /* Process command line */ for (i = 1; i < argc; i++) { /* Find option */ cmdline_opt_t *opt = cmdline_opt_find(cmdline_opts, ARRAY_SIZE(cmdline_opts), argv[i]); if (!opt) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), "invalid option specified [%s]", argv[i]); /* Process */ if (opt->type == OPT_BOOL) *((int*)opt->param) = 1; else if (++i == argc) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), "option %s requires a value", opt->lopt); else if (opt->type == OPT_INT) *((int*)opt->param) = atoi(argv[i]); else if (opt->type == OPT_STR_LIST) { str_list_t *strl = opt->param; if (strl->num < strl->max) strl->str[strl->num++] = argv[i]; } else *((char**)opt->param) = argv[i]; /* Stop processing */ if (opt_help) show_usage(argv[0], cmdline_opts, ARRAY_SIZE(cmdline_opts), NULL); if (opt_version) show_version(argv[0]); } /* Additional cmdline processing */ #if ENABLE_LINUXDVB if (!opt_dvb_adapters) { adapter_mask = ~0; } else { char *p, *e; char *r = NULL; char *dvb_adapters = strdup(opt_dvb_adapters); adapter_mask = 0x0; p = strtok_r(dvb_adapters, ",", &r); while (p) { int a = strtol(p, &e, 10); if (*e != 0 || a < 0 || a > 31) { tvhlog(LOG_ERR, "START", "Invalid adapter number '%s'", p); free(dvb_adapters); return 1; } adapter_mask |= (1 << a); p = strtok_r(NULL, ",", &r); } free(dvb_adapters); if (!adapter_mask) { tvhlog(LOG_ERR, "START", "No adapters specified!"); return 1; } } #endif if (tvheadend_webroot) { char *tmp; if (*tvheadend_webroot == '/') tmp = strdup(tvheadend_webroot); else { tmp = malloc(strlen(tvheadend_webroot)+2); *tmp = '/'; strcpy(tmp+1, tvheadend_webroot); } if (tmp[strlen(tmp)-1] == '/') tmp[strlen(tmp)-1] = '\0'; tvheadend_webroot = tmp; } tvheadend_webui_debug = opt_uidebug; /* Setup logging */ if (isatty(2)) log_options |= TVHLOG_OPT_DECORATE; if (opt_stderr || opt_syslog || opt_logpath) { if (!opt_log_trace && !opt_log_debug) log_debug = "all"; log_level = LOG_DEBUG; if (opt_stderr) log_options |= TVHLOG_OPT_DBG_STDERR; if (opt_syslog) log_options |= TVHLOG_OPT_DBG_SYSLOG; if (opt_logpath) log_options |= TVHLOG_OPT_DBG_FILE; } if (opt_fileline) log_options |= TVHLOG_OPT_FILELINE; if (opt_threadid) log_options |= TVHLOG_OPT_THREAD; if (opt_log_trace) { log_level = LOG_TRACE; log_trace = opt_log_trace; } if (opt_log_debug) log_debug = opt_log_debug; tvhlog_init(log_level, log_options, opt_logpath); tvhlog_set_debug(log_debug); tvhlog_set_trace(log_trace); signal(SIGPIPE, handle_sigpipe); // will be redundant later /* Daemonise */ if(opt_fork) { const char *homedir; gid_t gid; uid_t uid; struct group *grp = getgrnam(opt_group ?: "video"); struct passwd *pw = opt_user ? getpwnam(opt_user) : NULL; FILE *pidfile = fopen(opt_pidpath, "w+"); if(grp != NULL) { gid = grp->gr_gid; } else { gid = 1; } if (pw != NULL) { if (getuid() != pw->pw_uid) { gid_t glist[10]; int gnum; gnum = get_user_groups(pw, glist, 10); if (setgroups(gnum, glist)) { tvhlog(LOG_ALERT, "START", "setgroups() failed, do you have permission?"); return 1; } } uid = pw->pw_uid; homedir = pw->pw_dir; setenv("HOME", homedir, 1); } else { uid = 1; } if ((getgid() != gid) && setgid(gid)) { tvhlog(LOG_ALERT, "START", "setgid() failed, do you have permission?"); return 1; } if ((getuid() != uid) && setuid(uid)) { tvhlog(LOG_ALERT, "START", "setuid() failed, do you have permission?"); return 1; } if(daemon(0, 0)) { exit(2); } if(pidfile != NULL) { fprintf(pidfile, "%d\n", getpid()); fclose(pidfile); } /* Make dumpable */ if (opt_dump) { #ifdef PLATFORM_LINUX if (chdir("/tmp")) tvhwarn("START", "failed to change cwd to /tmp"); prctl(PR_SET_DUMPABLE, 1); #else tvhwarn("START", "Coredumps not implemented on your platform"); #endif } umask(0); } tvheadend_running = 1; /* Start log thread (must be done post fork) */ tvhlog_start(); /* Alter logging */ if (opt_fork) tvhlog_options &= ~TVHLOG_OPT_STDERR; if (!isatty(2)) tvhlog_options &= ~TVHLOG_OPT_DECORATE; /* Initialise clock */ pthread_mutex_lock(&global_lock); time(&dispatch_clock); /* Signal handling */ sigfillset(&set); sigprocmask(SIG_BLOCK, &set, NULL); trap_init(argv[0]); /* Initialise configuration */ uuid_init(); idnode_init(); config_init(opt_config); /** * Initialize subsystems */ api_init(); fsmonitor_init(); #if ENABLE_LIBAV libav_init(); transcoding_init(); #endif imagecache_init(); service_init(); #if ENABLE_TSFILE if(opt_tsfile.num) { tsfile_init(opt_tsfile_tuner ?: opt_tsfile.num); for (i = 0; i < opt_tsfile.num; i++) tsfile_add_file(opt_tsfile.str[i]); } #endif #if ENABLE_MPEGTS_DVB dvb_network_init(); #endif #if ENABLE_IPTV iptv_init(); #endif #if ENABLE_LINUXDVB linuxdvb_init(adapter_mask); #endif channel_init(); subscription_init(); access_init(opt_firstrun, opt_noacl); #if ENABLE_TIMESHIFT timeshift_init(); #endif http_client_init(); tcp_server_init(opt_ipv6); http_server_init(opt_bindaddr); webui_init(); service_mapper_init(); descrambler_init(); epggrab_init(); epg_init(); dvr_init(); htsp_init(opt_bindaddr); if(opt_subscribe != NULL) subscription_dummy_join(opt_subscribe, 1); avahi_init(); epg_updated(); // cleanup now all prev ref's should have been created pthread_mutex_unlock(&global_lock); /** * Wait for SIGTERM / SIGINT, but only in this thread */ sigemptyset(&set); sigaddset(&set, SIGTERM); sigaddset(&set, SIGINT); signal(SIGTERM, doexit); signal(SIGINT, doexit); pthread_sigmask(SIG_UNBLOCK, &set, NULL); tvhlog(LOG_NOTICE, "START", "HTS Tvheadend version %s started, " "running as PID:%d UID:%d GID:%d, CWD:%s CNF:%s", tvheadend_version, getpid(), getuid(), getgid(), getcwd(buf, sizeof(buf)), hts_settings_get_root()); if(opt_abort) abort(); mainloop(); tvhftrace("main", htsp_done); tvhftrace("main", http_server_done); tvhftrace("main", webui_done); tvhftrace("main", http_client_done); tvhftrace("main", fsmonitor_done); #if ENABLE_MPEGTS_DVB tvhftrace("main", dvb_network_done); #endif #if ENABLE_IPTV tvhftrace("main", iptv_done); #endif #if ENABLE_LINUXDVB tvhftrace("main", linuxdvb_done); #endif // Note: the locking is obviously a bit redundant, but without // we need to disable the gtimer_arm call in epg_save() pthread_mutex_lock(&global_lock); tvhftrace("main", epg_save); #if ENABLE_TIMESHIFT tvhftrace("main", timeshift_term); #endif pthread_mutex_unlock(&global_lock); tvhftrace("main", epggrab_done); tvhftrace("main", tcp_server_done); tvhftrace("main", descrambler_done); tvhftrace("main", service_mapper_done); tvhftrace("main", service_done); tvhftrace("main", channel_done); tvhftrace("main", dvr_done); tvhftrace("main", subscription_done); tvhftrace("main", access_done); tvhftrace("main", epg_done); tvhftrace("main", avahi_done); tvhftrace("main", imagecache_done); tvhftrace("main", idnode_done); tvhftrace("main", lang_code_done); tvhftrace("main", api_done); tvhftrace("main", config_done); tvhftrace("main", hts_settings_done); tvhftrace("main", dvb_done); tvhftrace("main", lang_str_done); tvhlog(LOG_NOTICE, "STOP", "Exiting HTS Tvheadend"); tvhlog_end(); if(opt_fork) unlink(opt_pidpath); free(opt_tsfile.str); return 0; }
/* Remember: svc_enabled() must be called before calling svc_start() */ int svc_start(svc_t *svc) { int respawn, sd = 0; pid_t pid; sigset_t nmask, omask; if (!svc) return 0; respawn = svc->pid != 0; /* Don't try and start service if it doesn't exist. */ if (!fexist(svc->cmd) && !svc->inetd.cmd) { char msg[80]; snprintf(msg, sizeof(msg), "Service %s does not exist!", svc->cmd); print_desc("", msg); print_result(1); return 0; } /* Ignore if finit is SIGSTOP'ed */ if (is_norespawn()) return 0; #ifndef INETD_DISABLED if (SVC_CMD_INETD == svc->type) { char ifname[IF_NAMESIZE] = "UNKNOWN"; sd = svc->inetd.watcher.fd; if (svc->inetd.type == SOCK_STREAM) { /* Open new client socket from server socket */ sd = accept(sd, NULL, NULL); if (sd < 0) { FLOG_PERROR("Failed accepting inetd service %d/tcp", svc->inetd.port); return 0; } _d("New client socket %d accepted for inetd service %d/tcp", sd, svc->inetd.port); /* Find ifname by means of getsockname() and getifaddrs() */ inetd_stream_peek(sd, ifname); } else { /* SOCK_DGRAM */ /* Find ifname by means of IP_PKTINFO sockopt --> ifindex + if_indextoname() */ inetd_dgram_peek(sd, ifname); } if (!inetd_is_allowed(&svc->inetd, ifname)) { FLOG_INFO("Service %s on port %d not allowed from interface %s.", svc->inetd.name, svc->inetd.port, ifname); if (svc->inetd.type == SOCK_STREAM) close(sd); return 0; } FLOG_INFO("Starting inetd service %s for requst from iface %s ...", svc->inetd.name, ifname); } else #endif if (SVC_CMD_SERVICE != svc->type) print_desc("", svc->desc); else if (!respawn) print_desc("Starting ", svc->desc); /* Block sigchild while forking. */ sigemptyset(&nmask); sigaddset(&nmask, SIGCHLD); sigprocmask(SIG_BLOCK, &nmask, &omask); pid = fork(); sigprocmask(SIG_SETMASK, &omask, NULL); if (pid == 0) { int i = 0; int status; #ifdef ENABLE_STATIC int uid = 0; /* XXX: Fix better warning that dropprivs is disabled. */ #else int uid = getuser(svc->username); #endif struct sigaction sa; char *args[MAX_NUM_SVC_ARGS]; sigemptyset(&nmask); sigaddset(&nmask, SIGCHLD); sigprocmask(SIG_UNBLOCK, &nmask, NULL); /* Reset signal handlers that were set by the parent process */ for (i = 1; i < NSIG; i++) DFLSIG(sa, i, 0); /* Set desired user */ if (uid >= 0) setuid(uid); /* Serve copy of args to process in case it modifies them. */ for (i = 0; i < (MAX_NUM_SVC_ARGS - 1) && svc->args[i][0] != 0; i++) args[i] = svc->args[i]; args[i] = NULL; /* Redirect inetd socket to stdin for service */ if (SVC_CMD_INETD == svc->type) { /* sd set previously */ dup2(sd, STDIN_FILENO); close(sd); dup2(STDIN_FILENO, STDOUT_FILENO); dup2(STDIN_FILENO, STDERR_FILENO); } else if (debug) { int fd; char buf[CMD_SIZE] = ""; fd = open(CONSOLE, O_WRONLY | O_APPEND); if (-1 != fd) { dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); close(fd); } for (i = 0; i < MAX_NUM_SVC_ARGS && args[i]; i++) { char arg[MAX_ARG_LEN]; snprintf(arg, sizeof(arg), "%s ", args[i]); if (strlen(arg) < (sizeof(buf) - strlen(buf))) strcat(buf, arg); } _e("%starting %s: %s", respawn ? "Res" : "S", svc->cmd, buf); } if (svc->inetd.cmd) status = svc->inetd.cmd(svc->inetd.type); else status = execv(svc->cmd, args); /* XXX: Maybe use execve() to be able to launch scripts? */ if (SVC_CMD_INETD == svc->type) { if (svc->inetd.type == SOCK_STREAM) { close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); } } exit(status); } svc->pid = pid; if (SVC_CMD_INETD == svc->type) { if (svc->inetd.type == SOCK_STREAM) close(sd); } else if (SVC_CMD_RUN == svc->type) print_result(WEXITSTATUS(complete(svc->cmd, pid))); else if (!respawn) print_result(svc->pid > 1 ? 0 : 1); return 0; }
/* Unblocks the interrupts */ void unblockInterrupts() { sigset_t signal_set; sigaddset(&signal_set, SIGALRM); sigprocmask(SIG_UNBLOCK, &signal_set, NULL); }
/* Main function */ int main(void) { int ret; pthread_t th_work, th_sig1, th_sig2; thestruct arg1, arg2; struct sigaction sa; /* Initialize output routine */ output_init(); /* We need to register the signal handlers for the PROCESS */ sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = sighdl1; if ((ret = sigaction(SIGUSR1, &sa, NULL)) == -1) { UNRESOLVED(ret, "Unable to register signal handler1"); } sa.sa_handler = sighdl2; if ((ret = sigaction(SIGUSR2, &sa, NULL)) == -1) { UNRESOLVED(ret, "Unable to register signal handler2"); } /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ sigemptyset(&usersigs); ret = sigaddset(&usersigs, SIGUSR1); ret |= sigaddset(&usersigs, SIGUSR2); if (ret != 0) { UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); } /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread"); } #ifdef WITH_SYNCHRO if (sem_init(&semsig1, 0, 1)) { UNRESOLVED(errno, "Semsig1 init"); } if (sem_init(&semsig2, 0, 1)) { UNRESOLVED(errno, "Semsig2 init"); } #endif if ((ret = pthread_create(&th_work, NULL, test, NULL))) { UNRESOLVED(ret, "Worker thread creation failed"); } arg1.sig = SIGUSR1; arg2.sig = SIGUSR2; #ifdef WITH_SYNCHRO arg1.sem = &semsig1; arg2.sem = &semsig2; #endif if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } /* Let's wait for a while now */ sleep(1); /* Now stop the threads and join them */ do { do_it = 0; } while (do_it); if ((ret = pthread_join(th_sig1, NULL))) { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } if ((ret = pthread_join(th_sig2, NULL))) { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } if ((ret = pthread_join(th_work, NULL))) { UNRESOLVED(ret, "Worker thread join failed"); } #if VERBOSE > 0 output("Test executed successfully.\n"); output(" %d initializations.\n", count_ope); #ifdef WITH_SYNCHRO output(" %d signals were sent meanwhile.\n", count_sig); #endif #endif PASSED; }
int main() { int fd1, fd2, sfd; fd_set read_set, write_set, except_set; char buf[10]; struct itimerval itv; struct timeval timeout; sigset_t waitset; struct signalfd_siginfo info; int n; fd1 = open("./pone", O_RDWR); fd2 = open("./ptwo", O_RDWR); sigemptyset(&waitset); sigaddset(&waitset, SIGALRM); sigprocmask(SIG_BLOCK, &waitset, NULL); sfd = signalfd(-1, &waitset, 0); itv.it_value.tv_sec = 1; // initial event itv.it_value.tv_usec = 10; itv.it_interval.tv_sec = 10; // periodic interval itv.it_interval.tv_usec = 0; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { perror("setitimer : "); exit(1); } FD_ZERO(&read_set); FD_SET(fd1, &read_set); FD_SET(fd2, &read_set); FD_SET(sfd, &read_set); while (1) { timeout.tv_sec = 90; timeout.tv_usec = 0; n = select(FD_SETSIZE, &read_set, NULL, NULL, &timeout); if (n < 0) { perror("select "); exit(1); } printf("Time left %ld\n", timeout.tv_sec); // test whether fd1 is ready or not if (FD_ISSET(fd1, &read_set)) { printf(" reading from fd1 (pone)\n"); n = read(fd1, buf, 10); printf(" read %d from pone \n", n); } // test whether fd2 is ready or not if (FD_ISSET(fd2, &read_set)) { printf(" reading from fd2 (ptwo)\n"); n = read(fd2, buf, 10); printf(" read %d from ptwo \n", n); } if (FD_ISSET(sfd, &read_set)) { read(sfd, &info, sizeof(struct signalfd_siginfo)); printf("got signal %d \n", info.ssi_signo); } } return 0; }
int /* O - Exit code */ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { const char *server_bin; /* CUPS_SERVERBIN environment variable */ char backends[1024]; /* Location of backends */ int request_id; /* Request ID */ int count; /* Number of devices from backend */ int compat; /* Compatibility device? */ char *backend_argv[2]; /* Arguments for backend */ cups_file_t *fp; /* Pipe to device backend */ int pid; /* Process ID of backend */ cups_dir_t *dir; /* Directory pointer */ cups_dentry_t *dent; /* Directory entry */ char filename[1024], /* Name of backend */ line[2048], /* Line from backend */ dclass[64], /* Device class */ uri[1024], /* Device URI */ info[128], /* Device info */ make_model[256], /* Make and model */ device_id[1024]; /* 1284 device ID */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ const char *requested; /* requested-attributes option */ int send_class, /* Send device-class attribute? */ send_info, /* Send device-info attribute? */ send_make_and_model, /* Send device-make-and-model attribute? */ send_uri, /* Send device-uri attribute? */ send_id; /* Send device-id attribute? */ dev_info_t *dev; /* Current device */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ setbuf(stderr, NULL); /* * Check the command-line... */ if (argc > 1) request_id = atoi(argv[1]); else request_id = 1; if (argc != 5) { fputs("Usage: cups-deviced request-id limit user-id options\n", stderr); return (1); } if (request_id < 1) { fprintf(stderr, "cups-deviced: Bad request ID %d!\n", request_id); return (1); } normal_user = atoi(argv[3]); if (normal_user <= 0) { fprintf(stderr, "cups-deviced: Bad user %d!\n", normal_user); return (1); } num_options = cupsParseOptions(argv[4], 0, &options); requested = cupsGetOption("requested-attributes", num_options, options); if (!requested || strstr(requested, "all")) { send_class = 1; send_info = 1; send_make_and_model = 1; send_uri = 1; send_id = 1; } else { send_class = strstr(requested, "device-class") != NULL; send_info = strstr(requested, "device-info") != NULL; send_make_and_model = strstr(requested, "device-make-and-model") != NULL; send_uri = strstr(requested, "device-uri") != NULL; send_id = strstr(requested, "device-id") != NULL; } /* * Try opening the backend directory... */ if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL) server_bin = CUPS_SERVERBIN; snprintf(backends, sizeof(backends), "%s/backend", server_bin); if ((dir = cupsDirOpen(backends)) == NULL) { fprintf(stderr, "ERROR: [cups-deviced] Unable to open backend directory " "\"%s\": %s", backends, strerror(errno)); return (1); } /* * Setup the devices array... */ devs = cupsArrayNew((cups_array_func_t)compare_devs, NULL); /* * Loop through all of the device backends... */ while ((dent = cupsDirRead(dir)) != NULL) { /* * Skip entries that are not executable files... */ if (!S_ISREG(dent->fileinfo.st_mode) || (dent->fileinfo.st_mode & (S_IRUSR | S_IXUSR)) != (S_IRUSR | S_IXUSR)) continue; /* * Change effective users depending on the backend permissions... */ snprintf(filename, sizeof(filename), "%s/%s", backends, dent->filename); /* * Backends without permissions for normal users run as root, * all others run as the unprivileged user... */ backend_argv[0] = dent->filename; backend_argv[1] = NULL; fp = cupsdPipeCommand(&pid, filename, backend_argv, (dent->fileinfo.st_mode & (S_IRWXG | S_IRWXO)) ? normal_user : 0); /* * Collect the output from the backend... */ if (fp) { /* * Set an alarm for the first read from the backend; this avoids * problems when a backend is hung getting device information. */ #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ sigset(SIGALRM, sigalrm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGALRM); action.sa_handler = sigalrm_handler; sigaction(SIGALRM, &action, NULL); #else signal(SIGALRM, sigalrm_handler); #endif /* HAVE_SIGSET */ alarm_tripped = 0; count = 0; compat = !strcmp(dent->filename, "smb"); alarm(30); while (cupsFileGets(fp, line, sizeof(line))) { /* * Reset the alarm clock... */ alarm(30); /* * Each line is of the form: * * class URI "make model" "name" ["1284 device ID"] */ device_id[0] = '\0'; if (!strncasecmp(line, "Usage", 5)) compat = 1; else if (sscanf(line, "%63s%1023s%*[ \t]\"%255[^\"]\"%*[ \t]\"%127[^\"]\"" "%*[ \t]\"%1023[^\"]", dclass, uri, make_model, info, device_id) < 4) { /* * Bad format; strip trailing newline and write an error message. */ if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = '\0'; fprintf(stderr, "ERROR: [cups-deviced] Bad line from \"%s\": %s\n", dent->filename, line); compat = 1; break; } else { /* * Add the device to the array of available devices... */ dev = add_dev(dclass, make_model, info, uri, device_id); if (!dev) { cupsDirClose(dir); cupsFileClose(fp); kill(pid, SIGTERM); return (1); } fprintf(stderr, "DEBUG: [cups-deviced] Added device \"%s\"...\n", uri); count ++; } } /* * Turn the alarm clock off and close the pipe to the command... */ alarm(0); if (alarm_tripped) fprintf(stderr, "WARNING: [cups-deviced] Backend \"%s\" did not " "respond within 30 seconds!\n", dent->filename); cupsFileClose(fp); kill(pid, SIGTERM); /* * Hack for backends that don't support the CUPS 1.1 calling convention: * add a network device with the method == backend name. */ if (count == 0 && compat) { snprintf(line, sizeof(line), "Unknown Network Device (%s)", dent->filename); dev = add_dev("network", line, "Unknown", dent->filename, ""); if (!dev) { cupsDirClose(dir); return (1); } fprintf(stderr, "DEBUG: [cups-deviced] Compatibility device " "\"%s\"...\n", dent->filename); } } else fprintf(stderr, "WARNING: [cups-deviced] Unable to execute \"%s\" " "backend: %s\n", dent->filename, strerror(errno)); } cupsDirClose(dir); /* * Output the list of devices... */ puts("Content-Type: application/ipp\n"); cupsdSendIPPHeader(IPP_OK, request_id); cupsdSendIPPGroup(IPP_TAG_OPERATION); cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8"); cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US"); if ((count = atoi(argv[2])) <= 0) count = cupsArrayCount(devs); if (count > cupsArrayCount(devs)) count = cupsArrayCount(devs); for (dev = (dev_info_t *)cupsArrayFirst(devs); count > 0; count --, dev = (dev_info_t *)cupsArrayNext(devs)) { /* * Add strings to attributes... */ cupsdSendIPPGroup(IPP_TAG_PRINTER); if (send_class) cupsdSendIPPString(IPP_TAG_KEYWORD, "device-class", dev->device_class); if (send_info) cupsdSendIPPString(IPP_TAG_TEXT, "device-info", dev->device_info); if (send_make_and_model) cupsdSendIPPString(IPP_TAG_TEXT, "device-make-and-model", dev->device_make_and_model); if (send_uri) cupsdSendIPPString(IPP_TAG_URI, "device-uri", dev->device_uri); if (send_id) cupsdSendIPPString(IPP_TAG_TEXT, "device-id", dev->device_id); } cupsdSendIPPTrailer(); /* * Free the devices array and return... */ for (dev = (dev_info_t *)cupsArrayFirst(devs); dev; dev = (dev_info_t *)cupsArrayNext(devs)) free(dev); cupsArrayDelete(devs); return (0); }
/* * Mail a message on standard input to the people indicated * in the passed header. (Internal interface). */ void mail1(struct header *hp, int printheaders) { char *cp; char *nbuf; int pid; char **namelist; struct name *to, *nsto; FILE *mtf; /* * Collect user's mail from standard input. * Get the result as mtf. */ if ((mtf = collect(hp, printheaders)) == NULL) return; if (value("interactive") != NULL) { if (value("askcc") != NULL || value("askbcc") != NULL) { if (value("askcc") != NULL) grabh(hp, GCC); if (value("askbcc") != NULL) grabh(hp, GBCC); } else { printf("EOT\n"); (void)fflush(stdout); } } if (fsize(mtf) == 0) { if (value("dontsendempty") != NULL) goto out; if (hp->h_subject == NULL) printf("No message, no subject; hope that's ok\n"); else printf("Null message body; hope that's ok\n"); } /* * Now, take the user names from the combined * to and cc lists and do all the alias * processing. */ senderr = 0; to = usermap(cat(hp->h_bcc, cat(hp->h_to, hp->h_cc))); if (to == NULL) { printf("No recipients specified\n"); senderr++; } /* * Look through the recipient list for names with /'s * in them which we write to as files directly. */ to = outof(to, mtf, hp); if (senderr) savedeadletter(mtf); to = elide(to); if (count(to) == 0) goto out; if (value("recordrecip") != NULL) { /* * Before fixing the header, save old To:. * We do this because elide above has sorted To: list, and * we would like to save message in a file named by the first * recipient the user has entered, not the one being the first * after sorting happened. */ if ((nsto = malloc(sizeof(struct name))) == NULL) err(1, "Out of memory"); bcopy(hp->h_to, nsto, sizeof(struct name)); } fixhead(hp, to); if ((mtf = infix(hp, mtf)) == NULL) { fprintf(stderr, ". . . message lost, sorry.\n"); return; } namelist = unpack(cat(hp->h_smopts, to)); if (debug) { char **t; printf("Sendmail arguments:"); for (t = namelist; *t != NULL; t++) printf(" \"%s\"", *t); printf("\n"); goto out; } if (value("recordrecip") != NULL) { /* * Extract first recipient username from saved To: and use it * as a filename. */ if ((nbuf = malloc(strlen(detract(nsto, 0)) + 1)) == NULL) err(1, "Out of memory"); if ((cp = yanklogin(detract(nsto, 0), nbuf)) != NULL) (void)savemail(expand(nbuf), mtf); free(nbuf); free(nsto); } else if ((cp = value("record")) != NULL) (void)savemail(expand(cp), mtf); /* * Fork, set up the temporary mail file as standard * input for "mail", and exec with the user list we generated * far above. */ pid = fork(); if (pid == -1) { warn("fork"); savedeadletter(mtf); goto out; } if (pid == 0) { sigset_t nset; (void)sigemptyset(&nset); (void)sigaddset(&nset, SIGHUP); (void)sigaddset(&nset, SIGINT); (void)sigaddset(&nset, SIGQUIT); (void)sigaddset(&nset, SIGTSTP); (void)sigaddset(&nset, SIGTTIN); (void)sigaddset(&nset, SIGTTOU); prepare_child(&nset, fileno(mtf), -1); if ((cp = value("sendmail")) != NULL) cp = expand(cp); else cp = _PATH_SENDMAIL; execv(cp, namelist); warn("%s", cp); _exit(1); } if (value("verbose") != NULL) (void)wait_child(pid); else free_child(pid); out: (void)Fclose(mtf); }
void S_signals_set_handler(SV* handlersv, SV* namesv) { I32 i; /* Need to be careful with SvREFCNT_dec(), because that can have side * effects (due to closures). We must make sure that the new disposition * is in place before it is called. */ SV* to_dec = NULL; STRLEN len; const char *s; bool set_to_ignore = FALSE; bool set_to_default = FALSE; #ifdef HAS_SIGPROCMASK sigset_t set, save; SV* save_sv; #endif if ( SvROK(handlersv) ) { if ( SvTYPE(SvRV(handlersv)) != SVt_PVCV ) Perl_croak(aTHX_ "signal handler should be a code refernce, 'DEFAULT' or 'IGNORE'"); } else { const char *s = SvOK(handlersv) ? SvPV_const(handlersv, len) : "DEFAULT"; if ( strEQ(s,"IGNORE") ) set_to_ignore = TRUE; else if (strEQ(s,"DEFAULT")) set_to_default = TRUE; else Perl_croak(aTHX_ "signal handler should be a code reference or 'DEFAULT or 'IGNORE'"); } if (!PL_psig_ptr) { Newxz(PL_psig_ptr, SIG_SIZE, SV*); Newxz(PL_psig_name, SIG_SIZE, SV*); Newxz(PL_psig_pend, SIG_SIZE, int); } s = SvPV_const(namesv,len); i = whichsig(s); /* ...no, a brick */ if (i <= 0) { Perl_croak(aTHX_ "No such signal: SIG%s", s); } #ifdef HAS_SIGPROCMASK /* Avoid having the signal arrive at a bad time, if possible. */ sigemptyset(&set); sigaddset(&set,i); sigprocmask(SIG_BLOCK, &set, &save); ENTER; save_sv = newSVpvn((char *)(&save), sizeof(sigset_t)); SAVEFREESV(save_sv); SAVEDESTRUCTOR_X(restore_sigmask, save_sv); #endif PERL_ASYNC_CHECK(); #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS) if (!PL_sig_handlers_initted) Perl_csighandler_init(); #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS PL_sig_ignoring[i] = 0; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS PL_sig_defaulting[i] = 0; #endif SvREFCNT_dec(PL_psig_name[i]); to_dec = PL_psig_ptr[i]; PL_psig_ptr[i] = NULL; PL_psig_name[i] = newSVpvn(s, len); SvREADONLY_on(PL_psig_name[i]); if (SvROK(handlersv)) { PL_psig_ptr[i] = SvREFCNT_inc(SvRV(handlersv)); (void)rsignal(i, PL_csighandlerp); #ifdef HAS_SIGPROCMASK LEAVE; #endif if(to_dec) SvREFCNT_dec(to_dec); return; } if (set_to_ignore) { #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS PL_sig_ignoring[i] = 1; (void)rsignal(i, PL_csighandlerp); #else (void)rsignal(i, (Sighandler_t) SIG_IGN); #endif } else { #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS PL_sig_defaulting[i] = 1; (void)rsignal(i, PL_csighandlerp); #else (void)rsignal(i, (Sighandler_t) SIG_DFL); #endif } #ifdef HAS_SIGPROCMASK if(i) LEAVE; #endif if(to_dec) SvREFCNT_dec(to_dec); }
void *signal_receiving_thread(void *arg) { int i, ret, sig; long delta; long max, min; sigset_t set, oset; stats_container_t dat; stats_container_t hist; stats_quantiles_t quantiles; stats_record_t rec; stats_container_init(&dat, ITERATIONS); stats_container_init(&hist, HIST_BUCKETS); stats_quantiles_init(&quantiles, (int)log10(ITERATIONS)); debug(DBG_DEBUG, "Signal receiving thread running\n"); if ((sigaddset(&set, SIGNALNUMBER))) { perror("sigaddset:"); exit(1); } if ((ret = pthread_sigmask(SIG_BLOCK, &set, &oset))) { printf("pthread_sigmask returned %d\n", ret); exit(1); } /* Let the sending thread know that receiver is ready */ atomic_set(1, &flag); debug(DBG_DEBUG, "Signal receiving thread ready to receive\n"); if (latency_threshold) { latency_trace_enable(); latency_trace_start(); } /* Warm up */ for (i = 0; i < 5; i++) { sigwait(&set, &sig); atomic_set(1, &flag); } max = min = 0; fail = 0; debug(DBG_INFO, "\n\n"); for (i = 0; i < ITERATIONS; i++) { sigwait(&set, &sig); end = rt_gettime(); delta = (end - begin)/NS_PER_US; rec.x = i; rec.y = delta; stats_container_append(&dat, rec); if (i == 0 || delta < min) min = delta; if (delta > max) max = delta; if (delta > pass_criteria) fail++; debug(DBG_INFO, "Iteration %d: Took %ld us. Max = %ld us, " "Min = %ld us\n", i, delta, max, min); fflush(stdout); buffer_print(); if (latency_threshold && (delta > latency_threshold)) { atomic_set(2, &flag); break; } atomic_set(1, &flag); } if (latency_threshold) { latency_trace_stop(); if (i != ITERATIONS) { printf("Latency threshold (%luus) exceeded at iteration %d\n", latency_threshold, i); fflush(stdout); buffer_print(); latency_trace_print(); stats_container_resize(&dat, i + 1); } } stats_hist(&hist, &dat); stats_container_save("samples", "pthread_kill Latency Scatter Plot", "Iteration", "Latency (us)", &dat, "points"); stats_container_save("hist", "pthread_kill Latency Histogram", "Latency (us)", "Samples", &hist, "steps"); printf("\n"); printf("Min: %lu us\n", stats_min(&dat)); printf("Max: %lu us\n", stats_max(&dat)); printf("Avg: %.4f us\n", stats_avg(&dat)); printf("StdDev: %.4f us\n", stats_stddev(&dat)); printf("Quantiles:\n"); stats_quantiles_calc(&dat, &quantiles); stats_quantiles_print(&quantiles); printf("Failures: %d\n", fail); printf("Criteria: Time < %d us\n", (int)pass_criteria); printf("Result: %s", fail ? "FAIL" : "PASS"); printf("\n\n"); return NULL; }
int main(int argc,char ** argv) { if(argc != 3) { printf("invalid arguments"); return 0; } argv1=argv[1]; argv2=argv[2]; int status; int tube[5][2]; int tuber[5][2]; int pid; struct sigaction act; sigset_t mask; sigaddset(&mask,SIGUSR1); act.sa_handler=sigint_handler; act.sa_flags=0; act.sa_mask=mask; sigaction(SIGINT,&act,NULL); sigaction(SIGUSR1,&act,NULL); mkfifo(argv[1],S_IRUSR|S_IWUSR); mkfifo(argv[2],S_IRUSR|S_IWUSR); fdr=open(argv[1],O_RDONLY); fdw=open(argv[2],O_WRONLY); fdwr=open(argv[1],O_WRONLY); int len; char * devise=(char *)calloc(20,sizeof(char)); char * montant=(char *)calloc(20,sizeof(char)); char * buf=(char *)calloc(20,sizeof(char)); int i = 0; double d; while(i!=NB_CONVERTERS) { if(pipe(tube[i])==-1) { perror("pipe"); return -1; } if(pipe(tuber[i])==-1) { perror("pipe"); return -1; } if((pid=fork())==0) { pid+=i; break; } i++; } while(1) { i=0; if(pid>5) { read(fdr,&len,sizeof(int)); read(fdr,devise,len); read(fdr,&len,sizeof(int)); read(fdr,montant,len); printf("requete reçue %s %s\n",devise,montant); while(i!=5) { buf=determine_currency(i); len=strlen(buf); write(tube[i][1],&len,sizeof(int)); write(tube[i][1],buf,len); len=strlen(devise); write(tube[i][1],&len,sizeof(int)); write(tube[i][1],devise,len); d=atof(montant); write(tube[i][1],&d,sizeof(double)); /*d=convert(devise,buf,atof(montant)); write(tube[i][1],&d,sizeof(double));*/ i++; } i=0; while(nbsigusr!=NB_CONVERTERS) pause(); printf("nbsigusr reçu\n"); while(i!=NB_CONVERTERS) { read(tuber[i][0],&len,sizeof(int)); write(fdw,&len,sizeof(int)); read(tuber[i][0],devise,len); write(fdw,devise,len); read(tuber[i][0],&d,sizeof(double)); write(fdw,&d,sizeof(double)); i++; } i=0; } else { printf("%d\n",pid); read(tube[pid][0],&len,sizeof(int)); read(tube[pid][0],buf,len); read(tube[pid][0],&len,sizeof(int)); read(tube[pid][0],devise,len); read(tube[pid][0],&d,sizeof(double)); printf("*********%s ,%s, %f********** \n",devise,buf,d); d=convert(devise,buf,d); printf("kill(getppid(),SIGUSR1)\n"); kill(getppid(),SIGUSR1); len=strlen(buf); write(tuber[pid][1],&len,sizeof(int)); write(tuber[pid][1],buf,len); write(tuber[pid][1],&d,sizeof(double)); } } return EXIT_SUCCESS; }
int main(int argc, char **argv) { sigset_t block_mask, unblock_mask; struct sigaction sa; int ch; enum { FORCE_OPTION = CHAR_MAX + 1 }; static const struct option longopts[] = { { "append", no_argument, NULL, 'a' }, { "command", required_argument, NULL, 'c' }, { "return", no_argument, NULL, 'e' }, { "flush", no_argument, NULL, 'f' }, { "force", no_argument, NULL, FORCE_OPTION, }, { "quiet", no_argument, NULL, 'q' }, { "timing", optional_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; setlocale(LC_ALL, ""); setlocale(LC_NUMERIC, "C"); /* see comment above */ bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); while ((ch = getopt_long(argc, argv, "ac:efqt::Vh", longopts, NULL)) != -1) switch(ch) { case 'a': aflg = 1; break; case 'c': cflg = optarg; break; case 'e': eflg = 1; break; case 'f': fflg = 1; break; case FORCE_OPTION: forceflg = 1; break; case 'q': qflg = 1; break; case 't': if (optarg && !(timingfd = fopen(optarg, "w"))) err(EXIT_FAILURE, _("cannot open %s"), optarg); tflg = 1; break; case 'V': printf(_("%s from %s\n"), program_invocation_short_name, PACKAGE_STRING); exit(EXIT_SUCCESS); break; case 'h': usage(stdout); break; case '?': default: usage(stderr); } argc -= optind; argv += optind; if (argc > 0) fname = argv[0]; else { fname = DEFAULT_OUTPUT; die_if_link(fname); } if ((fscript = fopen(fname, aflg ? "a" : "w")) == NULL) { warn(_("cannot open %s"), fname); fail(); } shell = getenv("SHELL"); if (shell == NULL) shell = _PATH_BSHELL; getmaster(); if (!qflg) printf(_("Script started, file is %s\n"), fname); fixtty(); #ifdef HAVE_LIBUTEMPTER utempter_add_record(master, NULL); #endif /* setup SIGCHLD handler */ sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = finish; sigaction(SIGCHLD, &sa, NULL); /* init mask for SIGCHLD */ sigprocmask(SIG_SETMASK, NULL, &block_mask); sigaddset(&block_mask, SIGCHLD); sigprocmask(SIG_SETMASK, &block_mask, &unblock_mask); child = fork(); sigprocmask(SIG_SETMASK, &unblock_mask, NULL); if (child < 0) { warn(_("fork failed")); fail(); } if (child == 0) { sigprocmask(SIG_SETMASK, &block_mask, NULL); subchild = child = fork(); sigprocmask(SIG_SETMASK, &unblock_mask, NULL); if (child < 0) { warn(_("fork failed")); fail(); } if (child) dooutput(); else doshell(); } else { sa.sa_handler = resize; sigaction(SIGWINCH, &sa, NULL); } doinput(); return EXIT_SUCCESS; }
/************************************************************************ * Main function ***********************************************************************/ int main(int argc, char **argv) { XCape_t *self = malloc(sizeof(XCape_t)); int dummy, ch; static char default_mapping[] = "Num_Lock;Caps_Lock"; char *mapping = default_mapping; self->debug = False; while ((ch = getopt(argc, argv, "d")) != -1) { switch (ch) { case 'd': self->debug = True; break; default: fprintf(stdout, "Usage: %s [-d]\n", argv[0]); fprintf(stdout, "Runs as a daemon unless -d flag is set\n"); return EXIT_SUCCESS; } } self->data_conn = XOpenDisplay(NULL); self->ctrl_conn = XOpenDisplay(NULL); if (!self->data_conn || !self->ctrl_conn) { fprintf(stderr, "Unable to connect to X11 display. Is $DISPLAY set?\n"); exit(EXIT_FAILURE); } if (!XQueryExtension(self->ctrl_conn, "XTEST", &dummy, &dummy, &dummy)) { fprintf(stderr, "Xtst extension missing\n"); exit(EXIT_FAILURE); } if (!XRecordQueryVersion(self->ctrl_conn, &dummy, &dummy)) { fprintf(stderr, "Failed to obtain xrecord version\n"); exit(EXIT_FAILURE); } if (!XkbQueryExtension(self->ctrl_conn, &dummy, &dummy, &dummy, &dummy, &dummy)) { fprintf(stderr, "Failed to obtain xkb version\n"); exit(EXIT_FAILURE); } self->map = parse_mapping(self->ctrl_conn, mapping); if (self->map == NULL) exit(EXIT_FAILURE); if (self->debug != True) daemon(0, 0); sigemptyset(&self->sigset); sigaddset(&self->sigset, SIGINT); sigaddset(&self->sigset, SIGTERM); pthread_sigmask(SIG_BLOCK, &self->sigset, NULL); pthread_create(&self->sigwait_thread, NULL, sig_handler, self); XRecordRange *rec_range = XRecordAllocRange(); rec_range->device_events.first = KeyPress; rec_range->device_events.last = ButtonRelease; XRecordClientSpec client_spec = XRecordAllClients; self->record_ctx = XRecordCreateContext(self->ctrl_conn, 0, &client_spec, 1, &rec_range, 1); if (self->record_ctx == 0) { fprintf(stderr, "Failed to create xrecord context\n"); exit(EXIT_FAILURE); } XSync(self->ctrl_conn, False); if (!XRecordEnableContext(self->data_conn, self->record_ctx, intercept, (XPointer) self)) { fprintf(stderr, "Failed to enable xrecord context\n"); exit(EXIT_FAILURE); } if (!XRecordFreeContext(self->ctrl_conn, self->record_ctx)) { fprintf(stderr, "Failed to free xrecord context\n"); } XCloseDisplay(self->ctrl_conn); XCloseDisplay(self->data_conn); if (self->debug) fprintf(stdout, "main exiting\n"); return EXIT_SUCCESS; }
void zbx_on_exit(void) { zabbix_log(LOG_LEVEL_DEBUG, "zbx_on_exit() called"); if (NULL != threads) { int i; sigset_t set; /* ignore SIGCHLD signals in order for zbx_sleep() to work */ sigemptyset(&set); sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, NULL); for (i = 0; i < threads_num; i++) { if (threads[i]) { kill(threads[i], SIGTERM); threads[i] = ZBX_THREAD_HANDLE_NULL; } } zbx_free(threads); } free_metrics(); zbx_sleep(2); /* wait for all child processes to exit */ DBconnect(ZBX_DB_CONNECT_EXIT); free_database_cache(); free_configuration_cache(); DBclose(); #ifdef HAVE_OPENIPMI free_ipmi_handler(); #endif #ifdef HAVE_SQLITE3 zbx_remove_sqlite3_mutex(); #endif /* free vmware support */ if (0 != CONFIG_VMWARE_FORKS) zbx_vmware_destroy(); free_selfmon_collector(); unload_modules(); zabbix_log(LOG_LEVEL_INFORMATION, "Zabbix Proxy stopped. Zabbix %s (revision %s).", ZABBIX_VERSION, ZABBIX_REVISION); zabbix_close_log(); #if defined(PS_OVERWRITE_ARGV) setproctitle_free_env(); #endif exit(EXIT_SUCCESS); }
/* * Ok, this is the main fork-routine. * * It copies the process, and if successful kick-starts * it and waits for it to finish using the VM if required. */ long do_fork(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size, int __user *parent_tidptr, int __user *child_tidptr) { struct task_struct *p; int trace = 0; long nr; /* * Do some preliminary argument and permissions checking before we * actually start allocating stuff */ if (clone_flags & CLONE_NEWUSER) { if (clone_flags & CLONE_THREAD) return -EINVAL; /* hopefully this check will go away when userns support is * complete */ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) || !capable(CAP_SETGID)) return -EPERM; } /* * We hope to recycle these flags after 2.6.26 */ if (unlikely(clone_flags & CLONE_STOPPED)) { static int __read_mostly count = 100; if (count > 0 && printk_ratelimit()) { char comm[TASK_COMM_LEN]; count--; printk(KERN_INFO "fork(): process `%s' used deprecated " "clone flags 0x%lx\n", get_task_comm(comm, current), clone_flags & CLONE_STOPPED); } } /* * When called from kernel_thread, don't do user tracing stuff. */ if (likely(user_mode(regs))) trace = tracehook_prepare_clone(clone_flags); p = copy_process(clone_flags, stack_start, regs, stack_size, child_tidptr, NULL, trace); /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. */ if (!IS_ERR(p)) { struct completion vfork; trace_sched_process_fork(current, p); nr = task_pid_vnr(p); if (clone_flags & CLONE_PARENT_SETTID) put_user(nr, parent_tidptr); if (clone_flags & CLONE_VFORK) { p->vfork_done = &vfork; init_completion(&vfork); } audit_finish_fork(p); tracehook_report_clone(trace, regs, clone_flags, nr, p); /* * We set PF_STARTING at creation in case tracing wants to * use this to distinguish a fully live task from one that * hasn't gotten to tracehook_report_clone() yet. Now we * clear it and set the child going. */ p->flags &= ~PF_STARTING; if (unlikely(clone_flags & CLONE_STOPPED)) { /* * We'll start up with an immediate SIGSTOP. */ sigaddset(&p->pending.signal, SIGSTOP); set_tsk_thread_flag(p, TIF_SIGPENDING); __set_task_state(p, TASK_STOPPED); } else { wake_up_new_task(p, clone_flags); } tracehook_report_clone_complete(trace, regs, clone_flags, nr, p); if (clone_flags & CLONE_VFORK) { freezer_do_not_count(); wait_for_completion(&vfork); freezer_count(); tracehook_report_vfork_done(p, nr); } } else { nr = PTR_ERR(p); } return nr; }
int main(int argc, char *argv[]) { char buf[8192], ptyname[16], *username, *logfile; struct utmp utmp; struct sigaction act; sigset_t set; int mfd, sfd; ssize_t n; if (argc != 3) usage(); username = argv[1]; logfile = argv[2]; sigemptyset(&set); sigaddset(&set, SIGTERM); sigaddset(&set, SIGIO); if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block init"); if ((lg = fopen(logfile, "w")) == NULL) err(1, "fopen %s", logfile); if (setlinebuf(lg) != 0) err(1, "setlinebuf"); memset(&act, 0, sizeof(act)); act.sa_mask = set; act.sa_flags = SA_RESTART; act.sa_handler = terminate; if (sigaction(SIGTERM, &act, NULL) == -1) err(1, "sigaction SIGTERM"); if (sigaction(SIGINT, &act, NULL) == -1) err(1, "sigaction SIGINT"); if (openpty(&mfd, &sfd, ptyname, NULL, NULL) == -1) err(1, "openpty"); fprintf(lg, "openpty %s\n", ptyname); if ((tty = strrchr(ptyname, '/')) == NULL) errx(1, "tty: %s", ptyname); tty++; /* login(3) searches for a controlling tty, use the created one */ if (dup2(sfd, 1) == -1) err(1, "dup2 stdout"); memset(&utmp, 0, sizeof(utmp)); strlcpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); strlcpy(utmp.ut_name, username, sizeof(utmp.ut_name)); time(&utmp.ut_time); login(&utmp); fprintf(lg, "login %s %s\n", username, tty); act.sa_handler = iostdin; if (sigaction(SIGIO, &act, NULL) == -1) err(1, "sigaction SIGIO"); if (setpgid(0, 0) == -1) err(1, "setpgid"); if (fcntl(0, F_SETOWN, getpid()) == -1) err(1, "fcntl F_SETOWN"); if (fcntl(0, F_SETFL, O_ASYNC) == -1) err(1, "fcntl O_ASYNC"); act.sa_handler = timeout; if (sigaction(SIGALRM, &act, NULL) == -1) err(1, "sigaction SIGALRM"); if (alarm(30) == (unsigned int)-1) err(1, "alarm"); fprintf(lg, "%s: started\n", getprogname()); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) err(1, "sigprocmask unblock init"); /* do not block signals during read, it has to be interrupted */ while ((n = read(mfd, buf, sizeof(buf))) > 0) { if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block write"); fprintf(lg, ">>> "); if (fwrite(buf, 1, n, lg) != (size_t)n) err(1, "fwrite %s", logfile); if (buf[n-1] != '\n') fprintf(lg, "\n"); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) err(1, "sigprocmask unblock write"); } if (sigprocmask(SIG_BLOCK, &set, NULL) == -1) err(1, "sigprocmask block exit"); if (n < 0) err(1, "read %s", ptyname); fprintf(lg, "EOF %s\n", ptyname); if (logout(tty) == 0) errx(1, "logout %s", tty); fprintf(lg, "logout %s\n", tty); errx(3, "EOF"); }
/**************************************************************************** * * Subroutine state_thread * * Purpose: This is a thread that will be used as a target for triggering * all of the different thread states * * Parameters: None * * Returns: Nothing * * *****************************************************************************/ void * state_thread(void * arg) { int rc,x,coid; sigset_t myset; uint64_t timeout; struct sigevent myevent; pthread_t mythread; char buf[100]; while(1) { /* Syncronize with the main thread. */ pthread_barrier_wait(&global_barrier); switch (cur_state) { case STATE_DEAD: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the dead state by calling pthread_exit */ pthread_exit(NULL); /* Should never get here */ abort(); case STATE_READY: exit_now=0; for (x=0;x<_syspage_ptr->num_cpu;x++) pthread_create(NULL, NULL, ready_thread, NULL); /* Let the new threads get started */ sleep(1); case STATE_RUNNING: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the running state by just doing some work. * this should also trigger a ready state before * we are running */ x=0; while(x<10) x++; exit_now=1; while(x<1000) x++; exit_now=1; /* and unblock the parent */ pthread_barrier_wait(&global_barrier); break; case STATE_STOPPED: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(100); kill (child_pid, SIGSTOP); delay(10); kill (child_pid, SIGCONT); delay(100); pthread_barrier_wait(&global_barrier); break; case STATE_SEND: case STATE_REPLY: coid=ConnectAttach(0, getpid(), chid, _NTO_SIDE_CHANNEL, 0); /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger the SEND/REPLY blocked states */ MsgSend(coid, buf, 10, buf,10); pthread_barrier_wait(&global_barrier); break; case STATE_RECEIVE: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger a receive state */ rc=MsgReceive(chid, buf, sizeof(buf), NULL); MsgReply(rc, EOK, "ok", 3); pthread_barrier_wait(&global_barrier); break; case STATE_WAITTHREAD: /* Start the logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); /* Trigger a waitthread state */ pthread_create(NULL, NULL, nothing_thread, NULL); pthread_barrier_wait(&global_barrier); break; case STATE_SIGSUSPEND: memset(&myevent, 0, sizeof(myevent)); myevent.sigev_notify = SIGEV_UNBLOCK; timeout = 1*1000000000L; sigemptyset(&myset); sigaddset(&myset, SIGHUP); sigaddset(&myset, SIGBUS); sigaddset(&myset, SIGSEGV); sigaddset(&myset, SIGXCPU); sigaddset(&myset, SIGRTMIN); sigaddset(&myset, SIGRTMAX); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); TimerTimeout( CLOCK_REALTIME, _NTO_TIMEOUT_SIGSUSPEND,&myevent, &timeout, NULL ); SignalSuspend(&myset); pthread_barrier_wait(&global_barrier); break; case STATE_SIGWAITINFO: memset(&myevent, 0, sizeof(myevent)); myevent.sigev_notify = SIGEV_UNBLOCK; timeout = 1*1000000000L; sigemptyset(&myset); sigaddset(&myset, SIGHUP); sigaddset(&myset, SIGBUS); sigaddset(&myset, SIGSEGV); sigaddset(&myset, SIGXCPU); sigaddset(&myset, SIGRTMIN); sigaddset(&myset, SIGRTMAX); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); TimerTimeout( CLOCK_REALTIME, _NTO_TIMEOUT_SIGWAITINFO,&myevent, &timeout, NULL ); SignalWaitinfo(&myset,NULL); pthread_barrier_wait(&global_barrier); break; case STATE_NANOSLEEP: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); sleep(1); pthread_barrier_wait(&global_barrier); break; case STATE_MUTEX: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); pthread_mutex_lock(&mymutex); pthread_mutex_unlock(&mymutex); pthread_barrier_wait(&global_barrier); break; case STATE_CONDVAR: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); pthread_mutex_lock(&mymutex); pthread_cond_wait(&mycondvar, &mymutex); pthread_mutex_unlock(&mymutex); pthread_barrier_wait(&global_barrier); break; case STATE_JOIN: pthread_create(&mythread, NULL, nothing_thread, NULL); /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); delay(10); pthread_join(mythread, NULL); pthread_barrier_wait(&global_barrier); break; case STATE_SEM: /* Start logging */ rc=TraceEvent(_NTO_TRACE_STARTNOSTATE); assert(rc!=-1); sleep(1); sem_wait(&mysem); pthread_barrier_wait(&global_barrier); break; } } }
static int midotmdty_preinit(void) { struct hostent *serv; sigset_t sigs; int tmdty_pipe_in[2], tmdty_pipe_out[2]; const char *tmdty_capt = "-Or -o -"; const char *tmdty_opt_hc = "-ir 0"; char tmdty_sound_spec[200]; char *tmdty_cmd; #define T_MAX_ARGS 255 char *tmdty_args[T_MAX_ARGS]; char *ptr; int i; serv = gethostbyname(TMDTY_HOST); if (!serv) return FALSE; if ((data_sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) return FALSE; data_adr.sin_family = AF_INET; memcpy(&ctrl_adr.sin_addr.s_addr, serv->h_addr, sizeof(ctrl_adr.sin_addr.s_addr)); data_adr.sin_addr.s_addr = ctrl_adr.sin_addr.s_addr; if (pipe(tmdty_pipe_in) == -1 || pipe(tmdty_pipe_out) == -1) { perror("pipe()"); goto err_ds; } switch ((tmdty_pid = fork())) { case 0: close(tmdty_pipe_in[0]); close(tmdty_pipe_out[1]); dup2(tmdty_pipe_out[0], STDIN_FILENO); dup2(tmdty_pipe_in[1], STDOUT_FILENO); close(tmdty_pipe_out[0]); close(tmdty_pipe_in[1]); #if 1 /* redirect stderr to /dev/null */ close(STDERR_FILENO); open("/dev/null", O_WRONLY); #endif strcpy(tmdty_sound_spec, tmdty_opt_hc); if (TMDTY_FREQ) { char opt_buf[100]; sprintf(opt_buf, " --sampling-freq=%d", TMDTY_FREQ); strcat(tmdty_sound_spec, opt_buf); } if (TMDTY_MONO) strcat(tmdty_sound_spec, " --output-mono"); if (TMDTY_8BIT) strcat(tmdty_sound_spec, " --output-8bit"); if (TMDTY_UNS) strcat(tmdty_sound_spec, " --output-unsigned"); if (TMDTY_CAPT) { strcat(tmdty_sound_spec, " "); strcat(tmdty_sound_spec, tmdty_capt); } asprintf(&tmdty_cmd, "%s %s %s", TMDTY_BIN, TMDTY_ARGS, tmdty_sound_spec); ptr = tmdty_cmd; for (i = 0; i < T_MAX_ARGS; i++) { do tmdty_args[i] = strsep(&ptr, " "); while (tmdty_args[i] && !tmdty_args[i][0]); if (!tmdty_args[i]) break; } /* unblock SIGIO and SIGALRM as timidity may use it */ sigemptyset(&sigs); sigaddset(&sigs, SIGIO); sigaddset(&sigs, SIGALRM); signal(SIGIO, SIG_IGN); signal(SIGALRM, SIG_IGN); sigprocmask(SIG_UNBLOCK, &sigs, NULL); execvp(TMDTY_BIN, tmdty_args); free(tmdty_cmd); exit(1); break; case -1: perror("fork()"); close(tmdty_pipe_out[0]); close(tmdty_pipe_in[1]); close(tmdty_pipe_in[0]); close(tmdty_pipe_out[1]); goto err_ds; } close(tmdty_pipe_out[0]); close(tmdty_pipe_in[1]); ctrl_sock_in = tmdty_pipe_in[0]; ctrl_sock_out = tmdty_pipe_out[1]; return TRUE; err_ds: close(data_sock); return FALSE; }
static ngx_thread_value_t ngx_worker_thread_cycle(void *data) { ngx_thread_t *thr = data; sigset_t set; ngx_err_t err; ngx_core_tls_t *tls; ngx_cycle_t *cycle; cycle = (ngx_cycle_t *) ngx_cycle; sigemptyset(&set); sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL)); sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL)); err = ngx_thread_sigmask(SIG_BLOCK, &set, NULL); if (err) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, ngx_thread_sigmask_n " failed"); return (ngx_thread_value_t) 1; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "thread " NGX_TID_T_FMT " started", ngx_thread_self()); ngx_setthrtitle("worker thread"); tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log); if (tls == NULL) { return (ngx_thread_value_t) 1; } err = ngx_thread_set_tls(ngx_core_tls_key, tls); if (err != 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, ngx_thread_set_tls_n " failed"); return (ngx_thread_value_t) 1; } ngx_mutex_lock(ngx_posted_events_mutex); for ( ;; ) { thr->state = NGX_THREAD_FREE; if (ngx_cond_wait(thr->cv, ngx_posted_events_mutex) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_terminate) { thr->state = NGX_THREAD_EXIT; ngx_mutex_unlock(ngx_posted_events_mutex); ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "thread " NGX_TID_T_FMT " is done", ngx_thread_self()); return (ngx_thread_value_t) 0; } thr->state = NGX_THREAD_BUSY; if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_process_changes) { if (ngx_process_changes(cycle, 1) == NGX_ERROR) { return (ngx_thread_value_t) 1; } } } }
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ int do_signal(struct pt_regs *regs, sigset_t *oldset) { siginfo_t info; struct k_sigaction *ka; /* * We want the common case to go fast, which * is why we may in certain cases get here from * kernel mode. Just return without doing anything * if so. */ if (!user_mode(regs)) return 1; if (!oldset) oldset = ¤t->blocked; for (;;) { unsigned long signr; spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); /* We're back. Did the debugger cancel the sig? */ if (!(signr = current->exit_code)) continue; current->exit_code = 0; /* The debugger continued. Ignore SIGSTOP. */ if (signr == SIGSTOP) continue; /* Update the siginfo structure. Is this good? */ if (signr != info.si_signo) { info.si_signo = signr; info.si_errno = 0; info.si_code = SI_USER; info.si_pid = current->p_pptr->pid; info.si_uid = current->p_pptr->uid; } /* If the (new) signal is now blocked, requeue it. */ if (sigismember(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->sig->action[signr-1]; if (ka->sa.sa_handler == SIG_IGN) { if (signr != SIGCHLD) continue; /* Check for SIGCHLD: it's special. */ while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) /* nothing */; continue; } if (ka->sa.sa_handler == SIG_DFL) { int exit_code = signr; /* Init gets no signals it doesn't want. */ if (current->pid == 1) continue; switch (signr) { case SIGCONT: case SIGCHLD: case SIGWINCH: continue; case SIGTSTP: case SIGTTIN: case SIGTTOU: if (is_orphaned_pgrp(current->pgrp)) continue; /* FALLTHRU */ case SIGSTOP: current->state = TASK_STOPPED; current->exit_code = signr; if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) notify_parent(current, SIGCHLD); schedule(); continue; case SIGQUIT: case SIGILL: case SIGTRAP: case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: if (do_coredump(signr, regs)) exit_code |= 0x80; /* FALLTHRU */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } } /* Whee! Actually deliver the signal. */ handle_signal(signr, ka, &info, oldset, regs); return 1; } /* Did we come from a system call? */ if (PT_REGS_SYSCALL (regs)) { /* Restart the system call - no handlers present */ if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND || regs->gpr[GPR_RVAL] == -ERESTARTSYS || regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) { regs->gpr[12] = PT_REGS_SYSCALL (regs); regs->pc -= 12; /* 4 + 8 for microblaze return offset wierdness */ } } return 0; }
int main() { int p,i; int pid,statval; char snumproc[5],soml[12],stcpu[5],stes[5]; struct itimerval itimer; struct itimerval otimer; struct sigaction act; // Obtener los ciclos por tiempo sprintf(soml,"%d",(int) get_one_millisec_loop()); printf("%s\n",soml); // Crear semáforo para asegurarse que solo 1 proceso pueda ejecutar handler // non_reentrant=semget((key_t)5234, 1, 0666 | IPC_CREAT); // set_semvalue(1,non_reentrant); // Crear pipe para que el scheduller sepa cual proceso terminó E/S unlink("fifo0"); mkfifo("fifo0",0777); fp=fopen("fifo0","r+"); // Pedir los datos de entrada al usuario for(p=0;p<MAXPROC;p++) { printf("Proceso %d\n",p); printf(" Tiempo de llegada ....................... : "); scanf("%d",&proceso[p].tinicio); printf(" Tiempo de cpu ........................... : "); scanf("%d",&proceso[p].tcpu); printf(" Tiempo de entrada y salida .............. : "); scanf("%d",&proceso[p].tes); printf(" Prioridad (usar solo para fixed priority) : "); scanf("%d",&proceso[p].prioridad); tiempo_total+=proceso[p].tcpu; proceso[p].trestante=proceso[p].tcpu; proceso[p].estado=NUEVO; } // Crear los procesos for(p=0;p<MAXPROC;p++) { proceso[p].pid=fork(); if(proceso[p].pid==0) { kill(getpid(),SIGSTOP); //SIGSTOP:pause SIGCONT:continue process sprintf(snumproc,"%d",p); sprintf(stcpu,"%d",proceso[p].tcpu); sprintf(stes,"%d",proceso[p].tes); execlp("./proceso","proceso",snumproc,soml,stcpu,stes,NULL); } } printf("Proceso %d\n",getpid()); // Establece el handler para manejar las señales act.sa_handler=handler; sigaddset(&act.sa_mask,SIGALRM); sigaddset(&act.sa_mask,SIGUSR1); sigaddset(&act.sa_mask,SIGUSR2); act.sa_flags=SA_RESTART; sigaction(SIGALRM,&act,0);//signal inicializa new process act.sa_handler=handler; sigaddset(&act.sa_mask,SIGALRM); sigaddset(&act.sa_mask,SIGUSR1); sigaddset(&act.sa_mask,SIGUSR2); act.sa_flags=SA_RESTART; sigaction(SIGUSR1,&act,0); //signal solicita entrada y salida act.sa_handler=handler; sigaddset(&act.sa_mask,SIGALRM); sigaddset(&act.sa_mask,SIGUSR1); sigaddset(&act.sa_mask,SIGUSR2); act.sa_flags=SA_RESTART; sigaction(SIGUSR2,&act,0); //signal termina entrada y salida // Inicializa variables listos.ent=0; listos.sal=0; bloqueados.ent=0; bloqueados.sal=0; proceso_en_ejecucion=NINGUNO; // Inicia el timer itimer.it_interval.tv_sec=1;//quantum =1seg itimer.it_interval.tv_usec=0;//quantum +=0micros itimer.it_value.tv_sec=1; itimer.it_value.tv_usec=0; if(setitimer(ITIMER_REAL,&itimer,&otimer)<0) perror("Error en el settimer"); // Aquí vamos a esperar a los procesos for(p=0;p<MAXPROC;p++) { pid=wait(&statval); for(i=0;i<MAXPROC;i++) if(proceso[i].pid==pid) //checa que proceso fue el que termino { proceso_terminado=i; //setea el proceso terminado handler(SIGCHLD); //manda señal para avisar que este ha terminado } } // del_semvalue(non_reentrant); fclose(fp); exit(EXIT_SUCCESS); }
int main (int argc, char const *const *argv) { iopause_fd x[2] = { { -1, IOPAUSE_READ, 0 }, { -1, IOPAUSE_READ, 0 } } ; PROG = "s6-supervise" ; if (argc < 2) strerr_dieusage(100, USAGE) ; if (chdir(argv[1]) < 0) strerr_diefu2sys(111, "chdir to ", argv[1]) ; { register unsigned int proglen = str_len(PROG) ; register unsigned int namelen = str_len(argv[1]) ; char progname[proglen + namelen + 2] ; byte_copy(progname, proglen, PROG) ; progname[proglen] = ' ' ; byte_copy(progname + proglen + 1, namelen + 1, argv[1]) ; PROG = progname ; if (!fd_sanitize()) strerr_diefu1sys(111, "sanitize stdin and stdout") ; x[1].fd = s6_supervise_lock(S6_SUPERVISE_CTLDIR) ; if (!ftrigw_fifodir_make(S6_SUPERVISE_EVENTDIR, getegid(), 0)) strerr_diefu2sys(111, "mkfifodir ", S6_SUPERVISE_EVENTDIR) ; x[0].fd = selfpipe_init() ; if (x[0].fd == -1) strerr_diefu1sys(111, "init selfpipe") ; if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111, "ignore SIGPIPE") ; { sigset_t set ; sigemptyset(&set) ; sigaddset(&set, SIGTERM) ; sigaddset(&set, SIGHUP) ; sigaddset(&set, SIGQUIT) ; sigaddset(&set, SIGCHLD) ; if (selfpipe_trapset(&set) < 0) strerr_diefu1sys(111, "trap signals") ; } if (!ftrigw_clean(S6_SUPERVISE_EVENTDIR)) strerr_warnwu2sys("ftrigw_clean ", S6_SUPERVISE_EVENTDIR) ; { struct stat st ; if (stat("down", &st) == -1) { if (errno != ENOENT) strerr_diefu1sys(111, "stat down") ; } else status.flagwantup = 0 ; if (stat("nosetsid", &st) == -1) { if (errno != ENOENT) strerr_diefu1sys(111, "stat nosetsid") ; } else flagsetsid = 0 ; } tain_now_g() ; settimeout(0) ; tain_copynow(&status.stamp) ; announce() ; ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "s", 1) ; while (cont) { register int r = iopause_g(x, 2, &deadline) ; if (r < 0) strerr_diefu1sys(111, "iopause") ; else if (!r) (*actions[state][V_TIMEOUT])() ; else { if ((x[0].revents | x[1].revents) & IOPAUSE_EXCEPT) strerr_diefu1x(111, "iopause: trouble with pipes") ; if (x[0].revents & IOPAUSE_READ) handle_signals() ; else if (x[1].revents & IOPAUSE_READ) handle_control(x[1].fd) ; } } ftrigw_notifyb_nosig(S6_SUPERVISE_EVENTDIR, "x", 1) ; } return 0 ; }
static void action_synced_wait(svc_action_t * op, sigset_t *mask) { int status = 0; int timeout = op->timeout; int sfd = -1; time_t start = -1; struct pollfd fds[3]; int wait_rc = 0; #ifdef HAVE_SYS_SIGNALFD_H sfd = signalfd(-1, mask, SFD_NONBLOCK); if (sfd < 0) { crm_perror(LOG_ERR, "signalfd() failed"); } #else sfd = sigchld_pipe[0]; #endif fds[0].fd = op->opaque->stdout_fd; fds[0].events = POLLIN; fds[0].revents = 0; fds[1].fd = op->opaque->stderr_fd; fds[1].events = POLLIN; fds[1].revents = 0; fds[2].fd = sfd; fds[2].events = POLLIN; fds[2].revents = 0; crm_trace("Waiting for %d", op->pid); start = time(NULL); do { int poll_rc = poll(fds, 3, timeout); if (poll_rc > 0) { if (fds[0].revents & POLLIN) { svc_read_output(op->opaque->stdout_fd, op, FALSE); } if (fds[1].revents & POLLIN) { svc_read_output(op->opaque->stderr_fd, op, TRUE); } if (fds[2].revents & POLLIN) { #ifdef HAVE_SYS_SIGNALFD_H struct signalfd_siginfo fdsi; ssize_t s; s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) { crm_perror(LOG_ERR, "Read from signal fd %d failed", sfd); } else if (fdsi.ssi_signo == SIGCHLD) { #else if (1) { /* Clear out the sigchld pipe. */ char ch; while (read(sfd, &ch, 1) == 1); #endif wait_rc = waitpid(op->pid, &status, WNOHANG); if (wait_rc < 0){ crm_perror(LOG_ERR, "waitpid() for %d failed", op->pid); } else if (wait_rc > 0) { break; } } } } else if (poll_rc == 0) { timeout = 0; break; } else if (poll_rc < 0) { if (errno != EINTR) { crm_perror(LOG_ERR, "poll() failed"); break; } } timeout = op->timeout - (time(NULL) - start) * 1000; } while ((op->timeout < 0 || timeout > 0)); crm_trace("Child done: %d", op->pid); if (wait_rc <= 0) { int killrc = kill(op->pid, SIGKILL); op->rc = PCMK_OCF_UNKNOWN_ERROR; if (op->timeout > 0 && timeout <= 0) { op->status = PCMK_LRM_OP_TIMEOUT; crm_warn("%s:%d - timed out after %dms", op->id, op->pid, op->timeout); } else { op->status = PCMK_LRM_OP_ERROR; } if (killrc && errno != ESRCH) { crm_err("kill(%d, KILL) failed: %d", op->pid, errno); } /* * From sigprocmask(2): * It is not possible to block SIGKILL or SIGSTOP. Attempts to do so are silently ignored. * * This makes it safe to skip WNOHANG here */ waitpid(op->pid, &status, 0); } else if (WIFEXITED(status)) { op->status = PCMK_LRM_OP_DONE; op->rc = WEXITSTATUS(status); crm_info("Managed %s process %d exited with rc=%d", op->id, op->pid, op->rc); } else if (WIFSIGNALED(status)) { int signo = WTERMSIG(status); op->status = PCMK_LRM_OP_ERROR; crm_err("Managed %s process %d exited with signal=%d", op->id, op->pid, signo); } #ifdef WCOREDUMP if (WCOREDUMP(status)) { crm_err("Managed %s process %d dumped core", op->id, op->pid); } #endif svc_read_output(op->opaque->stdout_fd, op, FALSE); svc_read_output(op->opaque->stderr_fd, op, TRUE); close(op->opaque->stdout_fd); close(op->opaque->stderr_fd); #ifdef HAVE_SYS_SIGNALFD_H close(sfd); #endif } /* For an asynchronous 'op', returns FALSE if 'op' should be free'd by the caller */ /* For a synchronous 'op', returns FALSE if 'op' fails */ gboolean services_os_action_execute(svc_action_t * op, gboolean synchronous) { int stdout_fd[2]; int stderr_fd[2]; struct stat st; sigset_t *pmask; #ifdef HAVE_SYS_SIGNALFD_H sigset_t mask; sigset_t old_mask; #define sigchld_cleanup() do { \ if (sigismember(&old_mask, SIGCHLD) == 0) { \ if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) { \ crm_perror(LOG_ERR, "sigprocmask() failed to unblock sigchld"); \ } \ } \ } while (0) #else struct sigaction sa; struct sigaction old_sa; #define sigchld_cleanup() do { \ if (sigaction(SIGCHLD, &old_sa, NULL) < 0) { \ crm_perror(LOG_ERR, "sigaction() failed to remove sigchld handler"); \ } \ close(sigchld_pipe[0]); \ close(sigchld_pipe[1]); \ sigchld_pipe[0] = sigchld_pipe[1] = -1; \ } while(0) #endif /* Fail fast */ if(stat(op->opaque->exec, &st) != 0) { int rc = errno; crm_warn("Cannot execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc); services_handle_exec_error(op, rc); if (!synchronous) { return operation_finalize(op); } return FALSE; } if (pipe(stdout_fd) < 0) { int rc = errno; crm_err("pipe(stdout_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc); services_handle_exec_error(op, rc); if (!synchronous) { return operation_finalize(op); } return FALSE; } if (pipe(stderr_fd) < 0) { int rc = errno; close(stdout_fd[0]); close(stdout_fd[1]); crm_err("pipe(stderr_fd) failed. '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc); services_handle_exec_error(op, rc); if (!synchronous) { return operation_finalize(op); } return FALSE; } if (synchronous) { #ifdef HAVE_SYS_SIGNALFD_H sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigemptyset(&old_mask); if (sigprocmask(SIG_BLOCK, &mask, &old_mask) < 0) { crm_perror(LOG_ERR, "sigprocmask() failed to block sigchld"); } pmask = &mask; #else if(pipe(sigchld_pipe) == -1) { crm_perror(LOG_ERR, "pipe() failed"); } set_fd_opts(sigchld_pipe[0], O_NONBLOCK); set_fd_opts(sigchld_pipe[1], O_NONBLOCK); sa.sa_handler = sigchld_handler; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGCHLD, &sa, &old_sa) < 0) { crm_perror(LOG_ERR, "sigaction() failed to set sigchld handler"); } pmask = NULL; #endif } op->pid = fork(); switch (op->pid) { case -1: { int rc = errno; close(stdout_fd[0]); close(stdout_fd[1]); close(stderr_fd[0]); close(stderr_fd[1]); crm_err("Could not execute '%s': %s (%d)", op->opaque->exec, pcmk_strerror(rc), rc); services_handle_exec_error(op, rc); if (!synchronous) { return operation_finalize(op); } sigchld_cleanup(); return FALSE; } case 0: /* Child */ close(stdout_fd[0]); close(stderr_fd[0]); if (STDOUT_FILENO != stdout_fd[1]) { if (dup2(stdout_fd[1], STDOUT_FILENO) != STDOUT_FILENO) { crm_err("dup2() failed (stdout)"); } close(stdout_fd[1]); } if (STDERR_FILENO != stderr_fd[1]) { if (dup2(stderr_fd[1], STDERR_FILENO) != STDERR_FILENO) { crm_err("dup2() failed (stderr)"); } close(stderr_fd[1]); } if (synchronous) { sigchld_cleanup(); } action_launch_child(op); CRM_ASSERT(0); /* action_launch_child is effectively noreturn */ } /* Only the parent reaches here */ close(stdout_fd[1]); close(stderr_fd[1]); op->opaque->stdout_fd = stdout_fd[0]; set_fd_opts(op->opaque->stdout_fd, O_NONBLOCK); op->opaque->stderr_fd = stderr_fd[0]; set_fd_opts(op->opaque->stderr_fd, O_NONBLOCK); if (synchronous) { action_synced_wait(op, pmask); sigchld_cleanup(); } else { crm_trace("Async waiting for %d - %s", op->pid, op->opaque->exec); mainloop_child_add_with_flags(op->pid, op->timeout, op->id, op, (op->flags & SVC_ACTION_LEAVE_GROUP) ? mainloop_leave_pid_group : 0, operation_finished); op->opaque->stdout_gsource = mainloop_add_fd(op->id, G_PRIORITY_LOW, op->opaque->stdout_fd, op, &stdout_callbacks); op->opaque->stderr_gsource = mainloop_add_fd(op->id, G_PRIORITY_LOW, op->opaque->stderr_fd, op, &stderr_callbacks); services_add_inflight_op(op); } return TRUE; }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { const char *device_uri; /* Device URI */ char scheme[255], /* Scheme in URI */ hostname[1024], /* Hostname */ username[255], /* Username info */ resource[1024], /* Resource info (printer name) */ *options, /* Pointer to options */ *name, /* Name of option */ *value, /* Value of option */ sep, /* Separator character */ *filename, /* File to print */ title[256]; /* Title string */ int port; /* Port number */ char portname[256]; /* Port name (string) */ http_addrlist_t *addrlist; /* List of addresses for printer */ int snmp_enabled = 1; /* Is SNMP enabled? */ int snmp_fd; /* SNMP socket */ int fd; /* Print file */ int status; /* Status of LPD job */ int mode; /* Print mode */ int banner; /* Print banner page? */ int format; /* Print format */ int order; /* Order of control/data files */ int reserve; /* Reserve priviledged port? */ int sanitize_title; /* Sanitize title string? */ int manual_copies, /* Do manual copies? */ timeout, /* Timeout */ contimeout, /* Connection timeout */ copies; /* Number of copies */ ssize_t bytes = 0; /* Initial bytes read */ char buffer[16384]; /* Initial print buffer */ #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ int num_jobopts; /* Number of job options */ cups_option_t *jobopts = NULL; /* Job options */ /* * Make sure status messages are not buffered... */ setbuf(stderr, NULL); /* * Ignore SIGPIPE and catch SIGTERM signals... */ #ifdef HAVE_SIGSET sigset(SIGPIPE, SIG_IGN); sigset(SIGTERM, sigterm_handler); #elif defined(HAVE_SIGACTION) memset(&action, 0, sizeof(action)); action.sa_handler = SIG_IGN; sigaction(SIGPIPE, &action, NULL); sigemptyset(&action.sa_mask); sigaddset(&action.sa_mask, SIGTERM); action.sa_handler = sigterm_handler; sigaction(SIGTERM, &action, NULL); #else signal(SIGPIPE, SIG_IGN); signal(SIGTERM, sigterm_handler); #endif /* HAVE_SIGSET */ /* * Check command-line... */ if (argc == 1) { printf("network lpd \"Unknown\" \"%s\"\n", _cupsLangString(cupsLangDefault(), _("LPD/LPR Host or Printer"))); return (CUPS_BACKEND_OK); } else if (argc < 6 || argc > 7) { _cupsLangPrintf(stderr, _("Usage: %s job-id user title copies options [file]"), argv[0]); return (CUPS_BACKEND_FAILED); } num_jobopts = cupsParseOptions(argv[5], 0, &jobopts); /* * Extract the hostname and printer name from the URI... */ while ((device_uri = cupsBackendDeviceURI(argv)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer.")); sleep(10); if (getenv("CLASS") != NULL) return (CUPS_BACKEND_FAILED); } httpSeparateURI(HTTP_URI_CODING_ALL, device_uri, scheme, sizeof(scheme), username, sizeof(username), hostname, sizeof(hostname), &port, resource, sizeof(resource)); if (!port) port = 515; /* Default to port 515 */ if (!username[0]) { /* * If no username is in the device URI, then use the print job user... */ strlcpy(username, argv[2], sizeof(username)); } /* * See if there are any options... */ mode = MODE_STANDARD; banner = 0; format = 'l'; order = ORDER_CONTROL_DATA; reserve = RESERVE_ANY; manual_copies = 1; timeout = 300; contimeout = 7 * 24 * 60 * 60; #ifdef __APPLE__ /* * We want to pass UTF-8 characters by default, not re-map them (3071945) */ sanitize_title = 0; #else /* * Otherwise we want to re-map UTF-8 to "safe" characters by default... */ sanitize_title = 1; #endif /* __APPLE__ */ if ((options = strchr(resource, '?')) != NULL) { /* * Yup, terminate the device name string and move to the first * character of the options... */ *options++ = '\0'; /* * Parse options... */ while (*options) { /* * Get the name... */ name = options; while (*options && *options != '=' && *options != '+' && *options != '&') options ++; if ((sep = *options) != '\0') *options++ = '\0'; if (sep == '=') { /* * Get the value... */ value = options; while (*options && *options != '+' && *options != '&') options ++; if (*options) *options++ = '\0'; } else value = (char *)""; /* * Process the option... */ if (!_cups_strcasecmp(name, "banner")) { /* * Set the banner... */ banner = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "format") && value[0]) { /* * Set output format... */ if (strchr("cdfglnoprtv", value[0])) format = value[0]; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown format character: \"%c\"."), value[0]); } else if (!_cups_strcasecmp(name, "mode") && value[0]) { /* * Set control/data order... */ if (!_cups_strcasecmp(value, "standard")) mode = MODE_STANDARD; else if (!_cups_strcasecmp(value, "stream")) mode = MODE_STREAM; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown print mode: \"%s\"."), value); } else if (!_cups_strcasecmp(name, "order") && value[0]) { /* * Set control/data order... */ if (!_cups_strcasecmp(value, "control,data")) order = ORDER_CONTROL_DATA; else if (!_cups_strcasecmp(value, "data,control")) order = ORDER_DATA_CONTROL; else _cupsLangPrintFilter(stderr, "ERROR", _("Unknown file order: \"%s\"."), value); } else if (!_cups_strcasecmp(name, "reserve")) { /* * Set port reservation mode... */ if (!value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "rfc1179")) reserve = RESERVE_RFC1179; else if (!_cups_strcasecmp(value, "any")) reserve = RESERVE_ANY; else reserve = RESERVE_NONE; } else if (!_cups_strcasecmp(name, "manual_copies")) { /* * Set manual copies... */ manual_copies = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "sanitize_title")) { /* * Set sanitize title... */ sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "snmp")) { /* * Enable/disable SNMP stuff... */ snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "timeout")) { /* * Set the timeout... */ if (atoi(value) > 0) timeout = atoi(value); } else if (!_cups_strcasecmp(name, "contimeout")) { /* * Set the connection timeout... */ if (atoi(value) > 0) contimeout = atoi(value); } } } if (mode == MODE_STREAM) order = ORDER_CONTROL_DATA; /* * Find the printer... */ snprintf(portname, sizeof(portname), "%d", port); fputs("STATE: +connecting-to-device\n", stderr); fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname); while ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL) { _cupsLangPrintFilter(stderr, "INFO", _("Unable to locate printer \"%s\"."), hostname); sleep(10); if (getenv("CLASS") != NULL) { fputs("STATE: -connecting-to-device\n", stderr); exit(CUPS_BACKEND_FAILED); } } if (snmp_enabled) snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); else snmp_fd = -1; /* * Wait for data from the filter... */ if (argc == 6) { if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB)) return (CUPS_BACKEND_OK); else if (mode == MODE_STANDARD && (bytes = read(0, buffer, sizeof(buffer))) <= 0) return (CUPS_BACKEND_OK); } /* * If we have 7 arguments, print the file named on the command-line. * Otherwise, copy stdin to a temporary file and print the temporary * file. */ if (argc == 6 && mode == MODE_STANDARD) { /* * Copy stdin to a temporary file... */ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0) { perror("DEBUG: Unable to create temporary file"); return (CUPS_BACKEND_FAILED); } _cupsLangPrintFilter(stderr, "INFO", _("Copying print data.")); if (bytes > 0) write(fd, buffer, (size_t)bytes); backendRunLoop(-1, fd, snmp_fd, &(addrlist->addr), 0, 0, backendNetworkSideCB); } else if (argc == 6) { /* * Stream from stdin... */ filename = NULL; fd = 0; } else { filename = argv[6]; fd = open(filename, O_RDONLY); if (fd == -1) { _cupsLangPrintError("ERROR", _("Unable to open print file")); return (CUPS_BACKEND_FAILED); } } /* * Sanitize the document title... */ strlcpy(title, argv[3], sizeof(title)); if (sanitize_title) { /* * Sanitize the title string so that we don't cause problems on * the remote end... */ char *ptr; for (ptr = title; *ptr; ptr ++) if (!isalnum(*ptr & 255) && !isspace(*ptr & 255)) *ptr = '_'; } /* * Queue the job... */ if (argc > 6) { if (manual_copies) { manual_copies = atoi(argv[4]); copies = 1; } else { manual_copies = 1; copies = atoi(argv[4]); } status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, username, title, copies, banner, format, order, reserve, manual_copies, timeout, contimeout, cupsGetOption("job-originating-host-name", num_jobopts, jobopts)); if (!status) fprintf(stderr, "PAGE: 1 %d\n", atoi(argv[4])); } else status = lpd_queue(hostname, addrlist, resource + 1, fd, snmp_fd, mode, username, title, 1, banner, format, order, reserve, 1, timeout, contimeout, cupsGetOption("job-originating-host-name", num_jobopts, jobopts)); /* * Remove the temporary file if necessary... */ if (tmpfilename[0]) unlink(tmpfilename); if (fd) close(fd); if (snmp_fd >= 0) _cupsSNMPClose(snmp_fd); /* * Return the queue status... */ return (status); }