Пример #1
0
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));
        }
    }
}
Пример #3
0
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);
}
Пример #4
0
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;
}
Пример #5
0
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);
}
Пример #6
0
void Sigaddset(sigset_t *set, int signum)
{
    if (sigaddset(set, signum) < 0)
	unix_error("Sigaddset error");
    return;
}
Пример #7
0
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);
}
Пример #8
0
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(&gtimer_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;
}
Пример #9
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;
}
Пример #10
0
/* Unblocks the interrupts */
void unblockInterrupts()
{
  sigset_t signal_set;
  sigaddset(&signal_set, SIGALRM);
  sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
}
Пример #11
0
Файл: 6-1.c Проект: 1587/ltp
/* 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;
}
Пример #12
0
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;
}
Пример #13
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);
}
Пример #14
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);
}
Пример #15
0
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;
}
Пример #17
0
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;
}
Пример #18
0
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;
}
Пример #19
0
/************************************************************************
 * 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;
}
Пример #20
0
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);
}
Пример #21
0
/*
 *  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;
}
Пример #22
0
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");
}
Пример #23
0
/****************************************************************************
*
*						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;
			
		}
	}
	
}
Пример #24
0
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;
            }
        }
    }
}
Пример #26
0
/*
 * 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 = &current->blocked;

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->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(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->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(&current->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;
}
Пример #27
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);
}
Пример #28
0
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 ;
}
Пример #29
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;
}
Пример #30
0
Файл: lpd.c Проект: ezeep/cups
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);
}