コード例 #1
0
int main()
{
    fd_set rdset, wrset;
    int max;
    sigset_t chld_set;

    init();
    signal(SIGCHLD, sigchld_handler);
    signal(SIGPIPE, SIG_IGN);
    sigemptyset(&chld_set);
    sigaddset(&chld_set, SIGCHLD);


    for (;;) {
        sigprocmask(SIG_BLOCK, &chld_set, NULL);
        if (child_exited)
            reap_children();
        max = fill_fds_for_select(&rdset, &wrset);
        if (libvchan_buffer_space(ctrl_vchan) <=
                (int)sizeof(struct msg_header))
            FD_ZERO(&rdset);

        wait_for_vchan_or_argfd(ctrl_vchan, max, &rdset, &wrset);
        sigprocmask(SIG_UNBLOCK, &chld_set, NULL);

        while (libvchan_data_ready(ctrl_vchan))
            handle_server_cmd();

        if (FD_ISSET(trigger_fd, &rdset))
            handle_trigger_io();

        handle_terminated_fork_client(&rdset);
    }
}
コード例 #2
0
int main(int argc, char **argv)
{
    fd_set read_fdset, write_fdset;
    int i, opt;
    int max;
    sigset_t chld_set;

    while ((opt=getopt(argc, argv, "q")) != -1) {
        switch (opt) {
            case 'q':
                opt_quiet = 1;
                break;
            default: /* '?' */
                fprintf(stderr, "usage: %s [-q] domainid domain-name [default user]\n", argv[0]);
                exit(1);
        }
    }
    if (argc - optind < 2 || argc - optind > 3) {
        fprintf(stderr, "usage: %s [-q] domainid domain-name [default user]\n", argv[0]);
        exit(1);
    }
    remote_domain_id = atoi(argv[optind]);
    remote_domain_name = argv[optind+1];
    if (argc - optind >= 3)
        default_user = argv[optind+2];
    init(remote_domain_id);
    sigemptyset(&chld_set);
    sigaddset(&chld_set, SIGCHLD);
    signal(SIGCHLD, sigchld_handler);
    /*
     * The main event loop. Waits for one of the following events:
     * - message from client
     * - message from agent
     * - new client
     * - child exited
     */
    for (;;) {
        max = fill_fdsets_for_select(&read_fdset, &write_fdset);
        if (libvchan_buffer_space(vchan) <= (int)sizeof(struct msg_header))
            FD_ZERO(&read_fdset);	// vchan full - don't read from clients

        sigprocmask(SIG_BLOCK, &chld_set, NULL);
        if (child_exited)
            reap_children();
        wait_for_vchan_or_argfd(vchan, max, &read_fdset, &write_fdset);
        sigprocmask(SIG_UNBLOCK, &chld_set, NULL);

        if (FD_ISSET(qrexec_daemon_unix_socket_fd, &read_fdset))
            handle_new_client();

        while (libvchan_data_ready(vchan))
            handle_message_from_agent();

        for (i = 0; i <= max_client_fd; i++)
            if (clients[i].state != CLIENT_INVALID
                && FD_ISSET(i, &read_fdset))
                handle_message_from_client(i);
    }
}
コード例 #3
0
ファイル: io.c プロジェクト: pllopis/libxenvchan
int libvchan_read(struct libvchan *ctrl, void *data, size_t size)
{
    while (1) {
        int avail = libvchan_data_ready(ctrl);
        if (avail && size > avail)
            size = avail;
        if (avail)
            return do_recv(ctrl, data, size);
        if (!libvchan_is_open(ctrl))
            return -1;
        if (!ctrl->blocking)
            return 0;
        if (libvchan_wait(ctrl))
            return -1;
    }
}
コード例 #4
0
ファイル: io.c プロジェクト: AndrewX192/qubes-core
/**
        may sleep (only if no data is available for reading);
        may return less data than requested;
        returns the amount of data processed, -1 on error or peer close
*/        
int libvchan_read(struct libvchan *ctrl, char *data, int size)
{
	int avail, avail_contig;
	int real_idx;
	while ((avail = libvchan_data_ready(ctrl)) == 0)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (avail > size)
		avail = size;
	real_idx = (*ctrl->rd_cons) & (ctrl->rd_ring_size - 1);
	avail_contig = ctrl->rd_ring_size - real_idx;
	if (avail_contig < avail)
		avail = avail_contig;
	memcpy(data, ctrl->rd_ring + real_idx, avail);
	*ctrl->rd_cons += avail;
	if (do_notify(ctrl) < 0)
		return -1;
	return avail;
}
コード例 #5
0
static void thread_func(void *userdata)
{
    struct userdata *u = userdata;
    char buf[2048]; // max ring buffer size

    pa_assert(u);

    pa_log_debug("Thread starting up");

    pa_thread_mq_install(&u->thread_mq);
    for (;;) {
        struct pollfd *play_pollfd;
        struct pollfd *rec_pollfd;
        int ret;

        play_pollfd = pa_rtpoll_item_get_pollfd(u->play_rtpoll_item, NULL);
        rec_pollfd = pa_rtpoll_item_get_pollfd(u->rec_rtpoll_item, NULL);

        if (play_pollfd->revents & POLLIN) {
            if (libvchan_wait(u->play_ctrl) < 0)
                goto fail;
            play_pollfd->revents = 0;
        }

        if (rec_pollfd->revents & POLLIN) {
            if (libvchan_wait(u->rec_ctrl) < 0)
                goto fail;
            rec_pollfd->revents = 0;
        }

        /* Render some data and write it to the fifo */
        if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) {

            if (u->sink->thread_info.rewind_requested)
                pa_sink_process_rewind(u->sink, 0);

            if (libvchan_buffer_space(u->play_ctrl)) {
                if (process_sink_render(u) < 0)
                    goto fail;
            }
        }

        if (u->source->thread_info.state == PA_SOURCE_RUNNING) {
            while (libvchan_data_ready(u->rec_ctrl)) {
                if (process_source_data(u) < 0)
                    goto fail;
            }
        } else {
            /* discard the data */
            if (libvchan_data_ready(u->rec_ctrl))
                if (libvchan_read(u->rec_ctrl, buf, sizeof(buf)) < 0)
                    goto fail;
        }

        /* Hmm, nothing to do. Let's sleep */
        play_pollfd->events = POLLIN;
        rec_pollfd->events = POLLIN;

#if PA_CHECK_VERSION(6,0,0)
        if ((ret = pa_rtpoll_run(u->rtpoll)) < 0)
#else
        if ((ret = pa_rtpoll_run(u->rtpoll, true)) < 0)
#endif
            goto fail;

        if (ret == 0)
            goto finish;
    }

fail:
    /* If this was no regular exit from the loop we have to continue
     * processing messages until we received PA_MESSAGE_SHUTDOWN */
    pa_asyncmsgq_post(u->thread_mq.outq, PA_MSGOBJECT(u->core),
                      PA_CORE_MESSAGE_UNLOAD_MODULE, u->module,
                      0, NULL, NULL);
    pa_asyncmsgq_wait_for(u->thread_mq.inq, PA_MESSAGE_SHUTDOWN);

finish:
    pa_log_debug("Thread shutting down");
}
コード例 #6
0
static void select_loop(libvchan_t *vchan)
{
    fd_set select_set;
    fd_set wr_set;
    int max_fd;
    int ret;
    int vchan_fd;
    sigset_t selectmask;
    struct timespec zero_timeout = { 0, 0 };
    struct timespec select_timeout = { 10, 0 };
    struct buffer stdin_buf;

    sigemptyset(&selectmask);
    sigaddset(&selectmask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &selectmask, NULL);
    sigemptyset(&selectmask);
    buffer_init(&stdin_buf);
    /* remember to set back to blocking mode before closing the FD - this may
     * be not the only copy and some processes may misbehave when get
     * nonblocking FD for input/output
     */
    set_nonblock(local_stdin_fd);

    for (;;) {
        vchan_fd = libvchan_fd_for_select(vchan);
        FD_ZERO(&select_set);
        FD_ZERO(&wr_set);
        FD_SET(vchan_fd, &select_set);
        max_fd = vchan_fd;
        if (local_stdout_fd != -1 &&
                (size_t)libvchan_buffer_space(vchan) > sizeof(struct msg_header)) {
            FD_SET(local_stdout_fd, &select_set);
            if (local_stdout_fd > max_fd)
                max_fd = local_stdout_fd;
        }
        if (child_exited && local_stdout_fd == -1)
            check_child_status(vchan);
        if (local_stdin_fd != -1 && buffer_len(&stdin_buf)) {
            FD_SET(local_stdin_fd, &wr_set);
            if (local_stdin_fd > max_fd)
                max_fd = local_stdin_fd;
        }
        if ((local_stdin_fd == -1 || buffer_len(&stdin_buf) == 0) &&
                libvchan_data_ready(vchan) > 0) {
            /* check for other FDs, but exit immediately */
            ret = pselect(max_fd + 1, &select_set, &wr_set, NULL,
                    &zero_timeout, &selectmask);
        } else
            ret = pselect(max_fd + 1, &select_set, &wr_set, NULL,
                    &select_timeout, &selectmask);
        if (ret < 0) {
            if (errno == EINTR && local_pid > 0) {
                continue;
            } else {
                perror("select");
                do_exit(1);
            }
        }
        if (ret == 0) {
            if (!libvchan_is_open(vchan)) {
                /* remote disconnected witout a proper signaling */
                do_exit(1);
            }
        }
        if (FD_ISSET(vchan_fd, &select_set))
            libvchan_wait(vchan);
        if (buffer_len(&stdin_buf) &&
                local_stdin_fd != -1 &&
                FD_ISSET(local_stdin_fd, &wr_set)) {
            if (flush_client_data(local_stdin_fd, &stdin_buf) == WRITE_STDIN_ERROR) {
                perror("write stdin");
                close(local_stdin_fd);
                local_stdin_fd = -1;
            }
        }
        while (libvchan_data_ready(vchan))
            if (handle_vchan_data(vchan, &stdin_buf) != WRITE_STDIN_OK)
                break;

        if (local_stdout_fd != -1
                && FD_ISSET(local_stdout_fd, &select_set))
            handle_input(vchan);
    }
}