コード例 #1
0
ファイル: netjack_packet.c プロジェクト: jackaudio/jack2
// new poll using nanoseconds resolution and
// not waiting forever.
int
netjack_poll_deadline (int sockfd, jack_time_t deadline)
{
    struct pollfd fds;
    int poll_err = 0;
#if HAVE_PPOLL
    struct timespec timeout_spec = { 0, 0 };
#else
    int timeout;
#endif

    jack_time_t now = jack_get_time();
    if( now >= deadline )
        return 0;

    if( (deadline - now) >= 1000000 ) {
        jack_error( "deadline more than 1 second in the future, trimming it." );
        deadline = now + 500000;
    }
#if HAVE_PPOLL
    timeout_spec.tv_nsec = (deadline - now) * 1000;
#else
    timeout = lrintf( (float)(deadline - now) / 1000.0 );
#endif

    fds.fd = sockfd;
    fds.events = POLLIN;

#if HAVE_PPOLL
    poll_err = ppoll (&fds, 1, &timeout_spec, NULL);
#else
    poll_err = poll (&fds, 1, timeout);
#endif

    if (poll_err == -1) {
        switch (errno) {
            case EBADF:
                jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
                break;
            case EFAULT:
                jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
                break;
            case EINTR:
                jack_error ("Error %d: A signal occurred before any requested event", errno);
                break;
            case EINVAL:
                jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
                break;
            case ENOMEM:
                jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
                break;
        }
    }
    return poll_err;
}
コード例 #2
0
static int wait_for_complete(struct loopback_test *t)
{
	int number_of_events = 0;
	char dummy;
	int ret;
	int i;
	struct timespec *ts = NULL;
	struct sigaction sa;
	sigset_t mask_old, mask;

	sigemptyset(&mask);
	sigemptyset(&mask_old);
	sigaddset(&mask, SIGINT);
	sigprocmask(SIG_BLOCK, &mask, &mask_old);

	sa.sa_handler = handler;
	sa.sa_flags = 0;
	sigemptyset(&sa.sa_mask);
	if (sigaction(SIGINT, &sa, NULL) == -1) {
		fprintf(stderr, "sigaction error\n");
		return -1;
	}

	if (t->poll_timeout.tv_sec != 0)
		ts = &t->poll_timeout;

	while (1) {

		ret = ppoll(t->fds, t->poll_count, ts, &mask_old);
		if (ret <= 0) {
			stop_tests(t);
			fprintf(stderr, "Poll exit with errno %d\n", errno);
			return -1;
		}

		for (i = 0; i < t->poll_count; i++) {
			if (t->fds[i].revents & POLLPRI) {
				/* Dummy read to clear the event */
				read(t->fds[i].fd, &dummy, 1);
				number_of_events++;
			}
		}

		if (number_of_events == t->poll_count)
			break;
	}

	if (!is_complete(t)) {
		fprintf(stderr, "Iteration count did not finish!\n");
		return -1;
	}

	return 0;
}
コード例 #3
0
ファイル: io-util.c プロジェクト: TrumpOnLinux/systemd
int pipe_eof(int fd) {
        struct pollfd pollfd = {
                .fd = fd,
                .events = POLLIN|POLLHUP,
        };

        int r;

        r = poll(&pollfd, 1, 0);
        if (r < 0)
                return -errno;

        if (r == 0)
                return 0;

        return pollfd.revents & POLLHUP;
}

int fd_wait_for_event(int fd, int event, usec_t t) {

        struct pollfd pollfd = {
                .fd = fd,
                .events = event,
        };

        struct timespec ts;
        int r;

        r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
        if (r < 0)
                return -errno;

        if (r == 0)
                return 0;

        return pollfd.revents;
}

static size_t nul_length(const uint8_t *p, size_t sz) {
        size_t n = 0;

        while (sz > 0) {
                if (*p != 0)
                        break;

                n++;
                p++;
                sz--;
        }

        return n;
}
コード例 #4
0
ファイル: syscalls-2007.c プロジェクト: 520SRig/valgrind
int main (void)
{
#if defined(HAVE_SIGNALFD) && defined(HAVE_EVENTFD) \
    && defined(HAVE_EVENTFD_READ) && defined(HAVE_PPOLL)
  {
    sigset_t mask;
    int fd, fd2;
    eventfd_t ev;
    struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
    struct pollfd pfd[2];

    sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);
    fd = signalfd (-1, &mask, 0);
    sigaddset (&mask, SIGUSR2);
    fd = signalfd (fd, &mask, 0);
    fd2 = eventfd (5, 0);
    eventfd_read (fd2, &ev);
    pfd[0].fd = fd;
    pfd[0].events = POLLIN|POLLOUT;
    pfd[1].fd = fd2;
    pfd[1].events = POLLIN|POLLOUT;
    ppoll (pfd, 2, &ts, &mask);
  }
#endif

#if defined(HAVE_UTIMENSAT)
  unlink("/tmp/valgrind-utimensat-test");
  close (creat ("/tmp/valgrind-utimensat-test", S_IRUSR | S_IWUSR));
  {
    struct timespec ts2[2] = { [0].tv_sec = 10000000, [1].tv_sec = 20000000 };
    utimensat (AT_FDCWD, "/tmp/valgrind-utimensat-test", ts2, 0);
  }
  unlink("/tmp/valgrind-utimensat-test");
#endif

#if defined(HAVE_EPOLL_CREATE) && defined(HAVE_EPOLL_PWAIT)
  {
    int fd3;
    struct epoll_event evs[10];
    sigset_t mask;

    sigemptyset (&mask);
    sigaddset (&mask, SIGUSR1);
    sigaddset (&mask, SIGUSR2);
    fd3 = epoll_create (10);
    epoll_pwait (fd3, evs, 10, 0, &mask);
  }
#endif

  return 0;
}
コード例 #5
0
ファイル: lib.c プロジェクト: ipilcher/n5550
/*
 * Acts as a wrapper around read(2) with a timeout.  Updates *timeout with
 * remaining time on successful return (>= 0).  Returns # of bytes read (0 =
 * EOF, -1 = error, -2 = timeout, -3 = thread exit signal received).
 */
ssize_t fcd_lib_read(int fd, void *buf, size_t count, struct timespec *timeout)
{
	struct timespec deadline;
	struct pollfd pfd;
	ssize_t ret;

	if (fcd_lib_deadline(&deadline, timeout) == -1)
		return -1;

	pfd.fd = fd;
	pfd.events = POLLIN;

	while (!fcd_thread_exit_flag)
	{
		if (fcd_lib_remaining(timeout, &deadline) == -1)
			return -1;

		ret = ppoll(&pfd, 1, timeout, &fcd_mon_ppoll_sigmask);
		if (ret == -1) {
			if (errno == EINTR)
				continue;
			FCD_PERROR("ppoll");
			return -1;
		}

		if (ret == 0)
			return -2;

		/*
		 * Different file descriptors (regular files, pipes, sysfs/proc
		 * files, etc.) behave so differently that it's impossible to
		 * check revents in a meaningful way.
		 */

		ret = read(fd, buf, count);
		if (ret == -1) {
			if (errno == EAGAIN || errno == EWOULDBLOCK)
				continue;
			FCD_PERROR("read");
			return -1;
		}
		else {
			if (fcd_lib_remaining(timeout, &deadline) == -1)
				return -1;
			return ret;
		}
	}

	return -3;
}
コード例 #6
0
ファイル: lib.c プロジェクト: ipilcher/n5550
/*
 * Sleeps for the specified number of seconds, unless interrupted by a signal
 * (SIGUSR1).  Returns the thread-local value of fcd_thread_exit_flag (or -1 on
 * error).
 *
 * NOTE: Does not check fcd_thread_exit_flag before sleeping (assumes that
 * 	 SIGUSR1 has been blocked).
 */
int fcd_lib_monitor_sleep(time_t seconds)
{
	struct timespec ts;

	ts.tv_sec = seconds;
	ts.tv_nsec = 0;

	if (ppoll(NULL, 0, &ts, &fcd_mon_ppoll_sigmask) == -1
						&& errno != EINTR) {
		FCD_PERROR("ppoll");
		return -1;
	}

	return fcd_thread_exit_flag;
}
コード例 #7
0
ファイル: checkmore.c プロジェクト: community-ssu/mafw
/* qemu is angry when it sees GLib trying to poll(NULL, 0, ...). */
int poll(struct pollfd *pfd, nfds_t npfd, int timeout)
{
	if (!pfd && !npfd) {
		/* Empty set, emulate with select(2). */
		if (timeout >= 0) {
			struct timeval tv;

			tv.tv_sec  =  timeout / 1000;
			tv.tv_usec = (timeout % 1000) * 1000;
			return select(0, NULL, NULL, NULL, &tv);
		} else
			return select(0, NULL, NULL, NULL, NULL);
	} else {
		/* Emulate with ppoll(2). */
		if (timeout >= 0) {
			struct timespec ts;

			ts.tv_sec  =  timeout / 1000;
			ts.tv_nsec = (timeout % 1000) * 1000000;
			return ppoll(pfd, npfd, &ts, NULL);
		} else
			return ppoll(pfd, npfd, NULL, NULL);
	}
}
コード例 #8
0
ファイル: gfs.c プロジェクト: ITikhonov/avremu
int gfs_poll(uint64_t ns, uint8_t *r) {
    struct timespec t= {.tv_sec=0,.tv_nsec=ns};
    int ret=ppoll(&ep0,1,&t,0);
    if(ret<0) {
        perror("gfs ppoll");
    }
    if(ret) {
        struct usb_gadgetfs_event e;
        int ret=read(ep0.fd,&e,sizeof e);
        if(ret<=0) return 0;
        if(e.type==GADGETFS_SETUP) {
            memcpy(r,&e.u.setup,sizeof(e.u.setup));
            return 1;
        }
    }
    return 0;
}
コード例 #9
0
ファイル: ppoll_alarm.c プロジェクト: MIPS/external-valgrind
static void *
mythr(void *ignore)
{
    pthread_mutex_lock(&mutex);
    ready = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    sigset_t ss;
    sigfillset(&ss);
    while (1) {
        struct timespec ts = {10000, 0};
        ppoll(NULL, 0, &ts, &ss);
    }

    return NULL;
}
コード例 #10
0
ファイル: io-util.c プロジェクト: akavel/systemd-bootchart
int fd_wait_for_event(int fd, int event, usec_t t) {

        struct pollfd pollfd = {
                .fd = fd,
                .events = event,
        };

        struct timespec ts;
        int r;

        r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
        if (r < 0)
                return -errno;

        if (r == 0)
                return 0;

        return pollfd.revents;
}
コード例 #11
0
ファイル: utils.c プロジェクト: FreeBSDFoundation/freebsd
/*
 * Loop until the auditpipe returns something, check if it is what
 * we want, else repeat the procedure until ppoll(2) times out.
 */
static void
check_auditpipe(struct pollfd fd[], const char *auditregex, FILE *pipestream)
{
	struct timespec currtime, endtime, timeout;

	/* Set the expire time for poll(2) while waiting for syscall audit */
	ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC, &endtime));
	endtime.tv_sec += 10;
	timeout.tv_nsec = endtime.tv_nsec;

	for (;;) {
		/* Update the time left for auditpipe to return any event */
		ATF_REQUIRE_EQ(0, clock_gettime(CLOCK_MONOTONIC, &currtime));
		timeout.tv_sec = endtime.tv_sec - currtime.tv_sec;

		switch (ppoll(fd, 1, &timeout, NULL)) {
		/* ppoll(2) returns, check if it's what we want */
		case 1:
			if (fd[0].revents & POLLIN) {
				if (get_records(auditregex, pipestream))
					return;
			} else {
				atf_tc_fail("Auditpipe returned an "
				"unknown event %#x", fd[0].revents);
			}
			break;

		/* poll(2) timed out */
		case 0:
			atf_tc_fail("%s not found in auditpipe within the "
					"time limit", auditregex);
			break;

		/* poll(2) standard error */
		case -1:
			atf_tc_fail("Poll: %s", strerror(errno));
			break;

		default:
			atf_tc_fail("Poll returned too many file descriptors");
		}
	}
}
コード例 #12
0
ファイル: diod.c プロジェクト: alepharchives/diod
/* Thread to handle SIGHUP, SIGTERM, and new connections on listen ports.
 */
static void *
_service_loop (void *arg)
{
    sigset_t sigs;
    int i;

    sigfillset (&sigs);
    sigdelset (&sigs, SIGHUP);
    sigdelset (&sigs, SIGTERM);
    sigdelset (&sigs, SIGUSR1);

    switch (ss.mode) {
        case SRV_FILEDES:
            diod_sock_startfd (ss.srv, ss.rfdno, ss.wfdno, "stdin");
            break;
        case SRV_NORMAL:
        case SRV_SOCKTEST:
            break;
    }
    while (!ss.shutdown) {
        if (ss.reload) {
            diod_conf_init_config_file (NULL);
            np_usercache_flush (ss.srv);
            ss.reload = 0;
        }
        for (i = 0; i < ss.nfds; i++) {
            ss.fds[i].events = POLLIN;
            ss.fds[i].revents = 0;
        }
        if (ppoll (ss.fds, ss.nfds, NULL, &sigs) < 0) {
            if (errno == EINTR)
                continue;
            err_exit ("ppoll");
        }
        for (i = 0; i < ss.nfds; i++) {
            if ((ss.fds[i].revents & POLLIN)) {
                diod_sock_accept_one (ss.srv, ss.fds[i].fd);
            }
        }
    }
    return NULL;
}
コード例 #13
0
ファイル: Watchdog.cpp プロジェクト: EMATech/ffado
bool
Watchdog::WatchdogTask::Execute()
{
    // All watchdog threads share the need to sleep for m_interval usec, with
    // the ability for this to be interrupted early to speed up program exit.
    //
    // Use ppoll() rather than SystemTimeSource::SleepUsecRelative(m_interval)
    // so the stop message pipe can be monitored, permitting the interruption
    // of long timing intervals to facilitate program shutdown.
    struct pollfd fds;
    struct timespec ts;
    fds.fd = stop_msg_pipe[0];
    fds.events = POLLIN;
    ts.tv_sec = (m_interval / 1000000);
    ts.tv_nsec = (m_interval % 1000000) * 1000;
    if (ppoll(&fds, 1, &ts, NULL)==1 && fds.revents!=0) {
        debugOutput( DEBUG_LEVEL_VERBOSE, "(%p) watchdog %p received request to stop\n", this, &m_parent);
        return false;
    }
    return true;
}
コード例 #14
0
bool LinuxIPCHost::EventLoop() {
  while (true) {
    int status =
        TEMP_FAILURE_RETRY(ppoll(pfds_.data(), pfds_.size(), nullptr, nullptr));
    if (status < 1) {
      LOG_ERROR(LOG_TAG, "ppoll error");
      return false;
    }

    if (pfds_[kFdIpc].revents && !OnMessage()) {
      return false;
    }

    if (pfds_.size() == kPossibleFds &&
        pfds_[kFdGatt].revents &&
        !OnGattWrite()) {
      return false;
    }
  }
  return true;
}
コード例 #15
0
ファイル: init.c プロジェクト: arsv/sninit
static void pollctl(void)
{
	int r;
	struct pollfd pfd;
	struct timespec pts;
	struct timespec* ppts;

	pfd.fd = initctlfd;
	pfd.events = POLLIN;
	if(timetowait >= 0) {
		pts.tv_sec = timetowait;
		pts.tv_nsec = 0;
		ppts = &pts;
	} else {
		ppts = NULL;
	}

	r = ppoll(&pfd, 1, ppts, &defsigset);

	if(r < 0 && errno != EINTR) {
		/* Failed ppoll means the main loop becomes unconstrained,
		   making init uncontrollable and wasting cpu cycles.
		   To avoid that, let's try to slow things down a bit. */
		warn("poll failed: %m");

		sigset_t cursigset;
		pts.tv_sec = timetowait >= 0 ? timetowait : 1;
		pts.tv_nsec = 0;

		/* ppoll also handles sigmask-lifting, try to work around that */
		sigprocmask(SIG_SETMASK, &defsigset, &cursigset);
		nanosleep(&pts, NULL);
		sigprocmask(SIG_SETMASK, &cursigset, NULL);

		/* EINTR, on the other hand, is totally ok (SIGCHLD etc) */
	} else if(r > 0) {
		/* only one fd in pfd, so not that much choice here */
		state |= S_INITCTL;
	}
}
コード例 #16
0
ファイル: event_sdl.c プロジェクト: zintor/navit
void
event_sdl_watch_thread (GPtrArray *watch_list)
{
   struct pollfd *pfds = g_new0 (struct pollfd, watch_list->len);
   struct event_watch *ew;
   int ret;
   int idx;

   for (idx = 0; idx < watch_list->len; idx++ ) {
      ew = g_ptr_array_index (watch_list, idx);
      g_memmove (&pfds[idx], ew->pfd, sizeof(struct pollfd));
   }

   while ((ret = ppoll(pfds, watch_list->len, NULL, NULL)) > 0) {
      for (idx = 0; idx < watch_list->len; idx++ ) {
	 if (pfds[idx].revents == pfds[idx].events) {	/* The requested event happened, notify mainloop! */
	    ew = g_ptr_array_index (watch_list, idx);
	    dbg(lvl_debug,"watch(%p) event(%d) encountered\n", ew, pfds[idx].revents);

	    SDL_Event event;
	    SDL_UserEvent userevent;

	    userevent.type = SDL_USEREVENT;
	    userevent.code = SDL_USEREVENT_CODE_WATCH;
	    userevent.data1 = ew->cb;
	    userevent.data2 = NULL;

	    event.type = SDL_USEREVENT;
	    event.user = userevent;

	    SDL_PushEvent (&event);
	 }
      }
   }

   g_free(pfds);

   pthread_exit(0);
}
コード例 #17
0
ファイル: adnstest.c プロジェクト: SpivEgin/Openswan
void process_dns_results(void) {
    send_unsent_ADNS_queries();
    while(adns_any_in_flight()) {
        struct pollfd one;
        struct timespec waiting;
        int n;

        one.fd = adns_afd;
        one.events = POLLIN;
        waiting.tv_sec = 30;
        waiting.tv_nsec= 0;
        n = ppoll(&one, 1, &waiting, NULL);
        if(n==1 && one.revents & POLLIN) {
            handle_adns_answer();
        } else {
            DBG_log("poll failed with: %d", n);
            exit(5);
        }

        send_unsent_ADNS_queries();
    }
}
コード例 #18
0
ファイル: poll.c プロジェクト: Evangileon/asterisk
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
{
#if !defined(AST_POLL_COMPAT)
	struct timeval start = ast_tvnow();
#if defined(HAVE_PPOLL)
	struct timespec ts = { tv ? tv->tv_sec : 0, tv ? tv->tv_usec * 1000 : 0 };
	int res = ppoll(pArray, n_fds, tv ? &ts : NULL, NULL);
#else
	int res = poll(pArray, n_fds, tv ? tv->tv_sec * 1000 + tv->tv_usec / 1000 : -1);
#endif
	struct timeval after = ast_tvnow();
	if (res > 0 && tv && ast_tvdiff_ms(ast_tvadd(*tv, start), after) > 0) {
		*tv = ast_tvsub(*tv, ast_tvsub(after, start));
	} else if (res > 0 && tv) {
		*tv = ast_tv(0, 0);
	}
	return res;
#else
	ast_fdset read_descs, write_descs, except_descs;
	int ready_descriptors, max_fd = 0;

	FD_ZERO(&read_descs);
	FD_ZERO(&write_descs);
	FD_ZERO(&except_descs);

	if (pArray) {
		max_fd = map_poll_spec(pArray, n_fds, &read_descs, &write_descs, &except_descs);
	}

	ready_descriptors = ast_select(max_fd + 1, &read_descs, &write_descs, &except_descs, tv);

	if (ready_descriptors >= 0) {
		map_select_results(pArray, n_fds, &read_descs, &write_descs, &except_descs);
	}

	return ready_descriptors;
#endif
}
コード例 #19
0
ファイル: main.c プロジェクト: JayceYang/usbmuxd
static int main_loop(int listenfd)
{
	int to, cnt, i, dto;
	struct fdlist pollfds;
	struct timespec tspec;

	sigset_t empty_sigset;
	sigemptyset(&empty_sigset); // unmask all signals

	fdlist_create(&pollfds);
	while(!should_exit) {
		usbmuxd_log(LL_FLOOD, "main_loop iteration");
		to = usb_get_timeout();
		usbmuxd_log(LL_FLOOD, "USB timeout is %d ms", to);
		dto = device_get_timeout();
		usbmuxd_log(LL_FLOOD, "Device timeout is %d ms", dto);
		if(dto < to)
			to = dto;

		fdlist_reset(&pollfds);
		fdlist_add(&pollfds, FD_LISTEN, listenfd, POLLIN);
		usb_get_fds(&pollfds);
		client_get_fds(&pollfds);
		usbmuxd_log(LL_FLOOD, "fd count is %d", pollfds.count);

		tspec.tv_sec = to / 1000;
		tspec.tv_nsec = (to % 1000) * 1000000;
		cnt = ppoll(pollfds.fds, pollfds.count, &tspec, &empty_sigset);
		usbmuxd_log(LL_FLOOD, "poll() returned %d", cnt);
		if(cnt == -1) {
			if(errno == EINTR) {
				if(should_exit) {
					usbmuxd_log(LL_INFO, "Event processing interrupted");
					break;
				}
				if(should_discover) {
					should_discover = 0;
					usbmuxd_log(LL_INFO, "Device discovery triggered");
					usb_discover();
				}
			}
		} else if(cnt == 0) {
			if(usb_process() < 0) {
				usbmuxd_log(LL_FATAL, "usb_process() failed");
				fdlist_free(&pollfds);
				return -1;
			}
			device_check_timeouts();
		} else {
			int done_usb = 0;
			for(i=0; i<pollfds.count; i++) {
				if(pollfds.fds[i].revents) {
					if(!done_usb && pollfds.owners[i] == FD_USB) {
						if(usb_process() < 0) {
							usbmuxd_log(LL_FATAL, "usb_process() failed");
							fdlist_free(&pollfds);
							return -1;
						}
						done_usb = 1;
					}
					if(pollfds.owners[i] == FD_LISTEN) {
						if(client_accept(listenfd) < 0) {
							usbmuxd_log(LL_FATAL, "client_accept() failed");
							fdlist_free(&pollfds);
							return -1;
						}
					}
					if(pollfds.owners[i] == FD_CLIENT) {
						client_process(pollfds.fds[i].fd, pollfds.fds[i].revents);
					}
				}
			}
		}
	}
	fdlist_free(&pollfds);
	return 0;
}
コード例 #20
0
ファイル: stdio-bridge.c プロジェクト: benjarobin/systemd
                        ts = NULL;
                else {
                        usec_t nw;

                        nw = now(CLOCK_MONOTONIC);
                        if (t > nw)
                                t -= nw;
                        else
                                t = 0;

                        ts = timespec_store(&_ts, t);
                }

                {
                        struct pollfd p[3] = {
                                {.fd = fd,            .events = events_a, },
                                {.fd = STDIN_FILENO,  .events = events_b & POLLIN, },
                                {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};

                        r = ppoll(p, ELEMENTSOF(p), ts, NULL);
                }
                if (r < 0) {
                        log_error("ppoll() failed: %m");
                        goto finish;
                }
        }

finish:
        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
コード例 #21
0
ファイル: tap2tap.c プロジェクト: Yuanyiis/tap2tap
int run_tunnel(struct args *args, sigset_t *orig_mask) {
    char device[IFNAMSIZ];
    int fd = create_tap(args->iface, device, args->mtu);
    if (fd < 0) {
        fprintf(stderr, "unable to create tap device\n");
        return 1;
    }
    printf("tap device is: %s\n", device);

    if (args->up_script) {
        int ret = run_updown(args->up_script, device);
        if (ret != 0) {
            fprintf(stderr, "up script exited with status: %d\n", ret);
            return 1;
        }
    }

    // TODO: make the port and bind address configurable
    int sockfd = setup_socket(inet_addr("0.0.0.0"), 1234);
    if (sockfd < 0) {
        fprintf(stderr, "unable to create socket\n");
        return 1;
    }

    if (drop_privileges(args->uid, args->gid) != 0) {
        fprintf(stderr, "couldn't drop privileges\n");
        return 1;
    }

    // circular queues
    struct frame recv_queue[RECV_QUEUE] = {0};
    size_t recv_idx = 0;
    size_t recv_len = 0;

    struct frame send_queue[SEND_QUEUE] = {0};
    size_t send_idx = 0;
    size_t send_len = 0;

    struct timespec tm;
    memset(&tm, 0, sizeof tm);
    tm.tv_nsec = 10000000;  // 0.01 seconds

    struct pollfd fds[2];
    memset(&fds, 0, sizeof fds);
    fds[0].fd = fd;
    fds[1].fd = sockfd;

    struct sockaddr_in remote;
    memset(&remote, 0, sizeof remote);
    char has_remote = 0;

    if (args->remote) {
        remote.sin_family = AF_INET;
        remote.sin_port = htons(1234);
        has_remote = 1;

        remote.sin_addr.s_addr = inet_addr(args->remote);
        if (remote.sin_addr.s_addr == INADDR_NONE) {
            fprintf(stderr, "failed to parse remote: %s\n", args->remote);
            return 2;
        }
        fprintf(stderr, "running in client mode with remote: %s\n", args->remote);
    }


    fprintf(stderr, "tunnel is up\n");
    for (;;) {
        fds[0].events = POLLIN;
        if (recv_len > 0) {
            fds[0].events |= POLLOUT;
        }

        fds[1].events = POLLIN;
        if (send_len > 0 && has_remote) {
            fds[1].events |= POLLOUT;
        }

        int result = ppoll(fds, 2, &tm, orig_mask);
        if (result < 0) {
            if (errno != EINTR) {
                perror("ppoll");
                return 3;
            }
        }

        if (exit_wanted) {
            fprintf(stderr, "\nreceived signal %d, stopping tunnel\n", received_signal);
            break;
        }

        // tap can handle a write
        if (fds[0].revents & POLLOUT) {
            struct frame *f = &recv_queue[recv_idx];
            assert(f->len <= args->mtu + ETHERNET_HEADER);
            recv_idx = (recv_idx + 1) % RECV_QUEUE;
            recv_len -= 1;

            ssize_t n = write(fd, f->data, f->len);
            if (n < 0) {
                if (errno == EINVAL) {
                    fprintf(stderr, "received garbage frame\n");
                } else {
                    perror("write");
                    return 4;
                }
            } else if (n < f->len) {
                printf("[error] only wrote %zd bytes to tap (out of %zd bytes)\n", n, f->len);
            }
        }

        // udp socket can handle a write
        if (fds[1].revents & POLLOUT) {
            struct frame *f = &send_queue[send_idx];
            assert(f->len <= args->mtu + ETHERNET_HEADER);
            send_idx = (send_idx + 1) % SEND_QUEUE;
            send_len -= 1;

            ssize_t n = sendto(sockfd, f->data, f->len, 0, (struct sockaddr *) &remote, sizeof remote);
            if (n < 0) {
                perror("sendto");
                return 4;
            } else if (n < f->len) {
                printf("[error] only sent %zd bytes to peer (out of %zd bytes)\n", n, f->len);
            }
        }

        // tap has data for us to read
        if (fds[0].revents & POLLIN) {
            size_t idx = (send_idx + send_len) % SEND_QUEUE;

            if (send_len < SEND_QUEUE) {
                send_len += 1;
            } else {
                assert(send_len == SEND_QUEUE);
                printf("dropping frame from send queue\n");

                // put this packet at the end of the queue;
                // drop the first frame in the queue
                send_idx += 1;
            }

            struct frame *f = &send_queue[idx];
            memset(f, 0, sizeof(struct frame));
            ssize_t n = read(fd, &f->data, args->mtu + ETHERNET_HEADER);
            f->len = n;
        }

        // udp socket has data for us to read
        if (fds[1].revents & POLLIN) {
            size_t idx = (recv_idx + recv_len) % RECV_QUEUE;

            if (recv_len < RECV_QUEUE) {
                recv_len += 1;
            } else {
                assert(recv_len == RECV_QUEUE);
                printf("dropping frame from recv queue\n");

                // put this packet at the end of the queue;
                // drop the first frame in the queue
                recv_idx += 1;
            }

            struct frame *f = &recv_queue[idx];
            memset(f, 0, sizeof(struct frame));

            // TODO: handle case where remote changes, in both server+client mode
            socklen_t l = sizeof(remote);
            has_remote = 1;
            ssize_t n = recvfrom(
                sockfd,
                &f->data,
                args->mtu + ETHERNET_HEADER,
                0,
                (struct sockaddr *) &remote,
                &l
            );
            f->len = n;
        }
    }

    if (args->down_script) {
        int ret = run_updown(args->down_script, device);
        if (ret != 0) {
            fprintf(stderr, "down script exited with status: %d\n", ret);
            return 1;
        }
    }

    return 0;
}
コード例 #22
0
ファイル: block.c プロジェクト: BenjaminSchubert/rr
static void* reader_thread(void* dontcare) {
  char token = '!';
  int sock = sockfds[1];
  struct timeval ts;
  char c = '\0';
  int i;

  gettimeofday(&ts, NULL);

  atomic_puts("r: acquiring mutex ...");
  pthread_mutex_lock(&lock);
  atomic_puts("r:   ... releasing mutex");
  pthread_mutex_unlock(&lock);

  for (i = 0; i < 2; ++i) {
    atomic_puts("r: reading socket ...");
    gettimeofday(&ts, NULL);
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  /* TODO: readv() support */

  atomic_puts("r: recv'ing socket ...");
  gettimeofday(&ts, NULL);
  test_assert(1 == recv(sock, &c, sizeof(c), 0));
  atomic_printf("r:   ... recv'd '%c'\n", c);
  test_assert(c == token);
  ++token;

  atomic_puts("r: recvfrom'ing socket ...");
  test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));
  atomic_printf("r:   ... recvfrom'd '%c'\n", c);
  test_assert(c == token);
  ++token;
  {
    struct sockaddr_un addr;
    socklen_t addrlen = sizeof(addr);

    atomic_puts("r: recvfrom(&sock)'ing socket ...");
    test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, &addr, &addrlen));
    atomic_printf("r:   ... recvfrom'd '%c' from sock len:%d\n", c, addrlen);
    test_assert(c == token);
    /* socketpair() AF_LOCAL sockets don't identify
     * themselves. */
    test_assert(addrlen == 0);
    ++token;
  }
  {
    struct mmsghdr mmsg = { { 0 } };
    struct iovec data = { 0 };
    int magic = ~msg_magic;
    int err, ret;

    data.iov_base = &magic;
    data.iov_len = sizeof(magic);
    mmsg.msg_hdr.msg_iov = &data;
    mmsg.msg_hdr.msg_iovlen = 1;

    struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN);
    mmsg.msg_hdr.msg_control = cmptr;
    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;

    atomic_puts("r: recvmsg with DONTWAIT ...");
    ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);
    err = errno;
    atomic_printf("r:  ... returned %d (%s/%d)\n", ret, strerror(err), err);
    test_assert(-1 == ret);
    test_assert(EWOULDBLOCK == err);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    atomic_puts("r: recmsg'ing socket ...");

    test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));
    atomic_printf("r:   ... recvmsg'd 0x%x\n", magic);
    test_assert(msg_magic == magic);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    int fd = *(int*)CMSG_DATA(cmptr);
    struct stat fs_new, fs_old;
    fstat(fd, &fs_new);
    fstat(STDERR_FILENO, &fs_old);
    // check if control msg was send successfully
    test_assert(
        fs_old.st_dev == fs_new.st_dev && fs_old.st_ino == fs_new.st_ino &&
        fs_old.st_uid == fs_new.st_uid && fs_old.st_gid == fs_new.st_gid &&
        fs_old.st_rdev == fs_new.st_rdev && fs_old.st_size == fs_new.st_size);

    magic = ~msg_magic;
    atomic_puts("r: recmmsg'ing socket ...");

    breakpoint();
    test_assert(1 == recvmmsg(sock, &mmsg, 1, 0, NULL));
    atomic_printf("r:   ... recvmmsg'd 0x%x (%u bytes)\n", magic, mmsg.msg_len);
    test_assert(msg_magic == magic);
    test_assert(mmsg.msg_hdr.msg_iov == &data);

    magic = ~msg_magic;
#if defined(SYS_socketcall)
    struct recvmmsg_arg arg = { 0 };
    arg.sockfd = sock;
    arg.msgvec = &mmsg;
    arg.vlen = 1;
    test_assert(1 == syscall(SYS_socketcall, SYS_RECVMMSG, (void*)&arg));
#elif defined(SYS_recvmmsg)
    test_assert(1 == syscall(SYS_recvmmsg, sock, &mmsg, 1, 0, NULL));
#else
#error unable to call recvmmsg
#endif
    atomic_printf("r:   ... recvmmsg'd(by socketcall) 0x%x (%u bytes)\n", magic,
                  mmsg.msg_len);
    test_assert(msg_magic == magic);

    free(cmptr);
  }
  {
    struct msghdr msg = { 0 };
    struct iovec iovs[2];
    char c1 = '\0', c2 = '\0';

    iovs[0].iov_base = &c1;
    iovs[0].iov_len = sizeof(c1);
    iovs[1].iov_base = &c2;
    iovs[1].iov_len = sizeof(c2);

    msg.msg_iov = iovs;
    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

    atomic_puts("r: recmsg'ing socket with two iovs ...");
    test_assert(2 == recvmsg(sock, &msg, 0));
    atomic_printf("r:   ... recvmsg'd '%c' and '%c'\n", c1, c2);

    test_assert(c1 == token);
    token++;
    test_assert(c2 == token);
    token++;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    poll(&pfd, 1, -1);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    struct pollfd pfd;

    atomic_puts("r: polling socket ...");
    pfd.fd = sock;
    pfd.events = POLLIN;
    gettimeofday(&ts, NULL);
    ppoll(&pfd, 1, NULL, NULL);
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
#if defined(__i386__)
    struct select_arg arg = { 0 };
    arg.n_fds = sock + 1;
    arg.read = &fds;
    arg.write = NULL;
    arg.except = NULL;
    arg.timeout = &tv;
    ret = syscall(SYS_select, &arg);
#else
    ret = syscall(SYS_select, sock + 1, &fds, NULL, NULL, &tv);
#endif
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    test_assert(1 == ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    fd_set fds;
    const struct timeval infinity = { 1 << 30, 0 };
    struct timeval tv = infinity;
    int ret;

    atomic_puts("r: select()ing socket ...");
    FD_ZERO(&fds);
    FD_SET(sock, &fds);
    ret = select(sock + 1, &fds, NULL, NULL, &tv);
    atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n", ret, tv.tv_sec,
                  tv.tv_usec);
    test_assert(1 == ret);
    test_assert(FD_ISSET(sock, &fds));
    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;
  }
  {
    int epfd;
    struct epoll_event ev;

    atomic_puts("r: epolling socket ...");
    test_assert(0 <= (epfd = epoll_create(1 /*num events*/)));
    ev.events = EPOLLIN;
    ev.data.fd = sock;
    gettimeofday(&ts, NULL);
    test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));
    test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
    atomic_puts("r:   ... done, doing nonblocking read ...");
    test_assert(sock == ev.data.fd);
    test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
    test_assert(1 == read(sock, &c, sizeof(c)));
    atomic_printf("r:   ... read '%c'\n", c);
    test_assert(c == token);
    ++token;

    close(epfd);
  }
  {
    char* buf = (char*)malloc(num_sockbuf_bytes);
    ssize_t nwritten = 0;
    struct iovec iov;

    ++token;
    memset(buf, token, num_sockbuf_bytes);

    atomic_printf("r: writing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (nwritten < num_sockbuf_bytes) {
      ssize_t this_write = write(sock, buf, num_sockbuf_bytes - nwritten);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      nwritten += this_write;
    }

    ++token;
    memset(buf, token, num_sockbuf_bytes);
    iov.iov_base = buf;
    iov.iov_len = num_sockbuf_bytes;
    atomic_printf("r: writev()ing outbuf of size %zd ...\n", num_sockbuf_bytes);
    while (iov.iov_len > 0) {
      ssize_t this_write = writev(sock, &iov, 1);
      atomic_printf("r:   wrote %zd bytes this time\n", this_write);
      iov.iov_len -= this_write;
    }

    free(buf);
  }

  atomic_puts("r: reading socket with masked signals ...");
  {
    sigset_t old_mask, mask;
    sigfillset(&mask);
    test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, &old_mask));

    test_assert(1 == read(sock, &c, sizeof(c)));

    test_assert(0 == pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
  }
  ++token;
  atomic_printf("r:   ... read '%c'\n", c);
  test_assert(c == token);

  /* Make the main thread wait on our join() */
  atomic_puts("r: sleeping ...");
  usleep(500000);

  return NULL;
}
コード例 #23
0
ファイル: kernel.c プロジェクト: AltSysrq/soliloquy
    void outputfd(object obj) {
      fds[ix].fd = $(obj, $i_Producer_fd);
      fds[ix].events = POLLOUT;
    }
    each_o($$lo_producers, outputfd);

    sigset_t allow_all;
    sigemptyset(&allow_all);
#ifdef HAVE_PPOLL
    struct timespec timeout = {
      .tv_sec = $i_kernel_poll_duration_ms / 1000,
      .tv_nsec = ($i_kernel_poll_duration_ms % 1000) * 1000000L,
    };

    int ret = ppoll(fds, fdcount,
                    $y_kernel_poll_infinite? NULL : &timeout,
                    &allow_all);
#else
    // Race condition, but at worst will stall things until the next keystroke
    sigset_t oldsigset;
    sigprocmask(SIG_SETMASK, &allow_all, &oldsigset);
    int ret = poll(fds, fdcount,
                   $y_kernel_poll_infinite? -1 : $i_kernel_poll_duration_ms);
    sigprocmask(SIG_SETMASK, &oldsigset, NULL);
#endif

    if (ret == -1) {
      //Error
      if (errno != EINTR)
        perror("poll");
    } else if (ret) {
コード例 #24
0
ファイル: client.c プロジェクト: sluchin/calc
/**
 * ソケット送受信
 *
 * @param[in] sock ソケット
 * @return なし
 */
st_client
client_loop(int sock)
{
    int ready = 0;                   /* select戻り値 */
    struct timespec timeout;         /* タイムアウト値 */
    sigset_t sigmask;                /* シグナルマスク */
    st_client status = EX_SUCCESS;   /* ステータス */
#ifdef _USE_SELECT
    fd_set fds, rfds;                /* selectマスク */
#else
    struct pollfd targets[MAX_POLL]; /* poll */
#endif /* _USE_SELECT */

    dbglog("start: sock=%d", sock);

    if (atexit(exit_memfree)) {
        outlog("atexit");
        return EX_FAILURE;
    }

#ifdef _USE_SELECT
    /* マスクの設定 */
    FD_ZERO(&fds);              /* 初期化 */
    FD_SET(sock, &fds);         /* ソケットをマスク */
    FD_SET(STDIN_FILENO, &fds); /* 標準入力をマスク */
#endif /* _USE_SELECT */

    /* シグナルマスクの取得 */
    sigmask = get_sigmask();

    /* タイムアウト値初期化 */
    (void)memset(&timeout, 0, sizeof(struct timespec));
    timeout.tv_sec = 1; /* 1秒 */
    timeout.tv_nsec = 0;

    do {
#ifdef _USE_SELECT
        (void)memcpy(&rfds, &fds, sizeof(fd_set)); /* マスクコピー */
        ready = pselect(sock + 1, &rfds,
                        NULL, NULL, &timeout, &sigmask);
#else
        targets[STDIN_POLL].fd = STDIN_FILENO;
        targets[STDIN_POLL].events = POLLIN;
        targets[SOCK_POLL].fd = sock;
        targets[SOCK_POLL].events = POLLIN;
        ready = ppoll(targets, MAX_POLL, &timeout, &sigmask);
#endif /* _USE_SELECT */
        if (ready < 0) {
            if (errno == EINTR) /* 割り込み */
                break;
            /* selectエラー */
            outlog("select=%d", ready);
            return EX_FAILURE;
        } else if (ready) {
#ifdef _USE_SELECT
            if (FD_ISSET(STDIN_FILENO, &fds)) {
                /* 標準入力レディ */
                status = send_sock(sock);
                if (status == EX_EMPTY)
                    continue;
                if (status)
                    return status;
            }
            if (FD_ISSET(sock, &fds)) {
                /* ソケットレディ */
                status = read_sock(sock);
                if (status)
                    return status;
            }
#else
            if (targets[STDIN_POLL].revents & POLLIN) {
                /* 標準入力レディ */
                status = send_sock(sock);
                if (status == EX_EMPTY)
                    continue;
                if (status)
                    return status;
            }
            if (targets[SOCK_POLL].revents & POLLIN) {
                /* ソケットレディ */
                status = read_sock(sock);
                if (status)
                    return status;
            }
#endif /* _USE_SELECT */
        } else { /* タイムアウト */
            continue;
        }
    } while (!g_sig_handled);

    return EX_SIGNAL;
}
コード例 #25
0
ファイル: block.c プロジェクト: KurSh/rr
static void* reader_thread(void* dontcare) {
	char token = '!';
	int sock = sockfds[1];
	struct timeval ts;
	char c = '\0';
	int i;

	gettimeofday(&ts, NULL);

	atomic_puts("r: acquiring mutex ...");
	pthread_mutex_lock(&lock);
	atomic_puts("r:   ... releasing mutex");
	pthread_mutex_unlock(&lock);

	for (i = 0; i < 2; ++i) {
		atomic_puts("r: reading socket ...");
		gettimeofday(&ts, NULL);
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	/* TODO: readv() support */

	atomic_puts("r: recv'ing socket ...");
	gettimeofday(&ts, NULL);
	test_assert(1 == recv(sock, &c, sizeof(c), 0));
	atomic_printf("r:   ... recv'd '%c'\n", c);
	test_assert(c == token);
	++token;

	atomic_puts("r: recvfrom'ing socket ...");
	test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));
	atomic_printf("r:   ... recvfrom'd '%c'\n", c);
	test_assert(c == token);
	++token;
	{
		struct sockaddr_un addr;
		socklen_t addrlen = sizeof(addr);

		atomic_puts("r: recvfrom(&sock)'ing socket ...");
		test_assert(1 == recvfrom(sock, &c, sizeof(c), 0,
					  &addr, &addrlen));
		atomic_printf("r:   ... recvfrom'd '%c' from sock len:%d\n",
			      c, addrlen);
		test_assert(c == token);
		/* socketpair() AF_LOCAL sockets don't identify
		 * themselves. */
		test_assert(addrlen == 0);
		++token;
	}
	{
		struct mmsghdr mmsg = {{ 0 }};
		struct iovec data = { 0 };
		int magic = ~msg_magic;
		int err, ret;

		data.iov_base = &magic;
		data.iov_len = sizeof(magic);
		mmsg.msg_hdr.msg_iov = &data;
		mmsg.msg_hdr.msg_iovlen = 1;

		atomic_puts("r: recvmsg with DONTWAIT ...");
		ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);
		err = errno;
		atomic_printf("r:  ... returned %d (%s/%d)\n",
			      ret, strerror(err), err);
		test_assert(-1 == ret && EWOULDBLOCK == err);

		atomic_puts("r: recmsg'ing socket ...");

		test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));
		atomic_printf("r:   ... recvmsg'd 0x%x\n", magic);
		test_assert(msg_magic == magic);

		magic = ~msg_magic;
		atomic_puts("r: recmmsg'ing socket ...");

		pthread_barrier_wait(&cheater_barrier);
		breakpoint();
		test_assert(1 == recvmmsg(sock, &mmsg, 1, 0, NULL));
		atomic_printf("r:   ... recvmmsg'd 0x%x (%u bytes)\n",
			      magic, mmsg.msg_len);
		test_assert(msg_magic == magic);
	}
	{
		struct msghdr msg = { 0 };
		struct iovec iovs[2];
		char c1 = '\0', c2 = '\0';

		iovs[0].iov_base = &c1;
		iovs[0].iov_len = sizeof(c1);
		iovs[1].iov_base = &c2;
		iovs[1].iov_len = sizeof(c2);

		msg.msg_iov = iovs;
		msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);

		atomic_puts("r: recmsg'ing socket with two iovs ...");
		test_assert(2 == recvmsg(sock, &msg, 0));
		atomic_printf("r:   ... recvmsg'd '%c' and '%c'\n", c1, c2);

		test_assert(c1 == token);
		token++;
		test_assert(c2 == token);
		token++;
	}
	{
		struct pollfd pfd;

		atomic_puts("r: polling socket ...");
		pfd.fd = sock;
		pfd.events = POLLIN;
		gettimeofday(&ts, NULL);
		poll(&pfd, 1, -1);
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		struct pollfd pfd;

		atomic_puts("r: polling socket ...");
		pfd.fd = sock;
		pfd.events = POLLIN;
		gettimeofday(&ts, NULL);
		ppoll(&pfd, 1, NULL, NULL);
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		fd_set fds;
		const struct timeval infinity = { 1 << 30, 0 };
		struct timeval tv = infinity;
		int ret;

		atomic_puts("r: select()ing socket ...");
		FD_ZERO(&fds);
		FD_SET(sock, &fds);
		ret = select(sock + 1, &fds, NULL, NULL, &tv);
		atomic_printf("r:   ... returned %d; tv { %ld, %ld }\n",
			      ret, tv.tv_sec, tv.tv_usec);
		test_assert(1 == ret);
		test_assert(FD_ISSET(sock, &fds));
		test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);

		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;
	}
	{
		int epfd;
		struct epoll_event ev;

		atomic_puts("r: epolling socket ...");
		test_assert(0 <= (epfd = epoll_create(1/*num events*/)));
		ev.events = EPOLLIN;
		ev.data.fd = sock;
		gettimeofday(&ts, NULL);
		test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd,
					   &ev));
		test_assert(1 == epoll_wait(epfd, &ev, 1, -1));
		atomic_puts("r:   ... done, doing nonblocking read ...");
		test_assert(sock == ev.data.fd);
		test_assert(1 == read(sock, &c, sizeof(c)));
		atomic_printf("r:   ... read '%c'\n", c);
		test_assert(c == token);
		++token;

		close(epfd);
	}
	{
		char* buf = (char*)malloc(num_sockbuf_bytes);
		ssize_t nwritten = 0;
		struct iovec iov;

		++token;
		memset(buf, token, num_sockbuf_bytes);

		atomic_printf("r: writing outbuf of size %d ...\n",
			      num_sockbuf_bytes);
		while (nwritten < num_sockbuf_bytes) {
			ssize_t this_write =
				write(sock, buf,
				      num_sockbuf_bytes - nwritten);
			atomic_printf("r:   wrote %d bytes this time\n",
				      this_write);
			nwritten += this_write;
		}

		++token;
		memset(buf, token, num_sockbuf_bytes);
		iov.iov_base = buf;
		iov.iov_len = num_sockbuf_bytes;
		atomic_printf("r: writev()ing outbuf of size %d ...\n",
			      num_sockbuf_bytes);
		while (iov.iov_len > 0) {
			ssize_t this_write = writev(sock, &iov, 1);
			atomic_printf("r:   wrote %d bytes this time\n",
				      this_write);
			iov.iov_len -= this_write;
		}

		free(buf);
	}

	atomic_puts("r: reading socket with masked signals ...");
	{
		sigset_t old_mask, mask;
		sigfillset(&mask);
		test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, &old_mask));

		test_assert(1 == read(sock, &c, sizeof(c)));

		test_assert(0 == pthread_sigmask(SIG_SETMASK, &old_mask, NULL));
	}
	++token;
	atomic_printf("r:   ... read '%c'\n", c);
	test_assert(c == token);

	/* Make the main thread wait on our join() */
	atomic_puts("r: sleeping ...");
	usleep(500000);

	return NULL;
}
コード例 #26
0
ファイル: websocket.c プロジェクト: 2AlNikkei/crouton
int main(int argc, char **argv) {
    int n;
    /* Poll array:
     * 0 - server_fd
     * 1 - pipein_fd
     * 2 - client_fd (if any)
     */
    struct pollfd fds[3];
    int nfds = 3;
    sigset_t sigmask;
    sigset_t sigmask_orig;
    struct sigaction act;
    int c;

    while ((c = getopt(argc, argv, "v:")) != -1) {
        switch (c) {
        case 'v':
            verbose = atoi(optarg);
            break;
        default:
            fprintf(stderr, "%s [-v 0-3]\n", argv[0]);
            return 1;
        }
    }

    /* Termination signal handler. */
    memset(&act, 0, sizeof(act));
    act.sa_handler = signal_handler;

    if (sigaction(SIGHUP, &act, 0) < 0 ||
        sigaction(SIGINT, &act, 0) < 0 ||
        sigaction(SIGTERM, &act, 0) < 0) {
        syserror("sigaction error.");
        return 2;
    }

    /* Ignore SIGPIPE in all cases: it may happen, since we write to pipes, but
     * it is not fatal. */
    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGPIPE);

    if (sigprocmask(SIG_BLOCK, &sigmask, NULL) < 0) {
        syserror("sigprocmask error.");
        return 2;
    }

    /* Ignore terminating signals, except when ppoll is running. Save current
     * mask in sigmask_orig. */
    sigemptyset(&sigmask);
    sigaddset(&sigmask, SIGHUP);
    sigaddset(&sigmask, SIGINT);
    sigaddset(&sigmask, SIGTERM);

    if (sigprocmask(SIG_BLOCK, &sigmask, &sigmask_orig) < 0) {
        syserror("sigprocmask error.");
        return 2;
    }

    /* Prepare pollfd structure. */
    memset(fds, 0, sizeof(fds));
    fds[0].events = POLLIN;
    fds[1].events = POLLIN;
    fds[2].events = POLLIN;

    /* Initialise pipe and WebSocket server */
    socket_server_init(PORT);
    pipe_init();

    while (!terminate) {
        /* Make sure fds is up to date. */
        fds[0].fd = server_fd;
        fds[1].fd = pipein_fd;
        fds[2].fd = client_fd;

        /* Only handle signals in ppoll: this makes sure we complete processing
         * the current request before bailing out. */
        n = ppoll(fds, nfds, NULL, &sigmask_orig);

        log(3, "poll ret=%d (%d, %d, %d)\n", n,
                   fds[0].revents, fds[1].revents, fds[2].revents);

        if (n < 0) {
            /* Do not print error when ppoll is interupted by a signal. */
            if (errno != EINTR || verbose >= 1)
                syserror("ppoll error.");
            break;
        }

        if (fds[0].revents & POLLIN) {
            log(1, "WebSocket accept.");
            socket_server_accept(VERSION);
            n--;
        }
        if (fds[1].revents & POLLIN) {
            log(2, "Pipe fd ready.");
            pipein_read();
            n--;
        }
        if (fds[2].revents & POLLIN) {
            log(2, "Client fd ready.");
            socket_client_read();
            n--;
        }

        if (n > 0) { /* Some events were not handled, this is a problem */
            error("Some poll events could not be handled: "
                    "ret=%d (%d, %d, %d).",
                    n, fds[0].revents, fds[1].revents, fds[2].revents);
            break;
        }
    }

    log(1, "Terminating...");

    if (client_fd)
        socket_client_close(1);

    return 0;
}
コード例 #27
0
ファイル: sixad-remote.cpp プロジェクト: Dzenik/crab_project
int main(int argc, char *argv[])
{
    struct pollfd p[3];
    struct timespec timeout;
    struct device_settings settings;
    struct sigaction sa;
    sigset_t sigs;
    short events;

    if (argc < 3) {
        std::cout << "Running " << argv[0] << " requires 'sixad'. Please run sixad instead" << std::endl;
        return 1;
    }

    const char *mac = argv[1];
    debug = atoi(argv[2]);

    open_log("sixad-remote");
    settings = init_values(mac);
    settings.joystick.axis = false;
    settings.joystick.sbuttons = false;
    settings.joystick.accel = false;
    settings.joystick.speed = false;
    settings.joystick.pos = false;;
    settings.led.enabled = false;
    settings.rumble.enabled = false;

    ufd = uinput_open(DEV_TYPE_REMOTE, mac, settings);

    if (ufd->js < 0 || ufd->mk < 0) {
        return 1;
    } else if (ufd->js == 0 && ufd->mk == 0) {
        syslog(LOG_ERR, "remote config has no joystick or input mode selected - please choose one!");
        return 1;
    }

    int modes = 0;
    if (settings.remote.numeric) modes |= REMOTE_KEYMODE_NUMBERIC;
    if (settings.remote.dvd) modes |= REMOTE_KEYMODE_DVD;
    if (settings.remote.directional) modes |= REMOTE_KEYMODE_DIRECTIONAL;
    if (settings.remote.multimedia) modes |= REMOTE_KEYMODE_MULTIMEDIA;

    sigfillset(&sigs);
//    sigdelset(&sigs, SIGCHLD);
//    sigdelset(&sigs, SIGPIPE);
//    sigdelset(&sigs, SIGTERM);
//    sigdelset(&sigs, SIGINT);
//    sigdelset(&sigs, SIGHUP);

    memset(&sa, 0, sizeof(sa));
    sa.sa_flags = SA_NOCLDSTOP;

    sa.sa_handler = sig_term;
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);

    sa.sa_handler = SIG_IGN;
    sigaction(SIGCHLD, &sa, NULL);
    sigaction(SIGPIPE, &sa, NULL);

    if (debug) syslog(LOG_INFO, "Press any to activate");

    p[0].fd = 0;
    p[0].events = POLLIN | POLLERR | POLLHUP;

    p[1].fd = 1;
    p[1].events = POLLIN | POLLERR | POLLHUP;

    p[2].fd = ufd->mk ? ufd->mk : ufd->js;
    p[2].events = POLLIN | POLLERR | POLLHUP;

    while (!io_canceled()) {
        int i, idx = 3;
        for (i = 0; i < idx; i++)
            p[i].revents = 0;

        timeout.tv_sec = 1;
        timeout.tv_nsec = 0;

        if (ppoll(p, idx, &timeout, &sigs) < 1)
            continue;

        if (p[1].revents & POLLIN) {
            process_remote(settings, mac, modes);
        }

        events = p[0].revents | p[1].revents | p[2].revents;

        if (events & (POLLERR | POLLHUP)) {
            break;
        }
    }

    if (debug) syslog(LOG_INFO, "Closing uinput...");

    if (settings.joystick.enabled) {
        uinput_close(ufd->js, debug);
    }
    if (settings.remote.enabled || settings.input.enabled) {
        uinput_close(ufd->mk, debug);
    }
    
    delete ufd;

    shutdown(isk, SHUT_RDWR);
    shutdown(csk, SHUT_RDWR);

    if (debug) syslog(LOG_INFO, "Done");

    return 0;
}
コード例 #28
0
ファイル: consumer.c プロジェクト: chenzhongtao/tcmu-runner
int main(int argc, char **argv)
{
	struct tcmulib_context *tcmulib_ctx;
	struct pollfd pollfds[16];
	int i;
	int ret;

	if (tcmu_setup_log()) {
		fprintf(stderr, "Could not setup tcmu logger.\n");
		exit(1);
	}

	/* If any TCMU devices that exist that match subtype,
	   handler->added() will now be called from within
	   tcmulib_initialize(). */
	tcmulib_ctx = tcmulib_initialize(&foo_handler, 1);
	if (tcmulib_ctx <= 0) {
		tcmu_err("tcmulib_initialize failed with %p\n", tcmulib_ctx);
		exit(1);
	}

	while (1) {
		pollfds[0].fd = tcmulib_get_master_fd(tcmulib_ctx);
		pollfds[0].events = POLLIN;
		pollfds[0].revents = 0;

		for (i = 0; i < dev_array_len; i++) {
			pollfds[i+1].fd = tcmu_get_dev_fd(tcmu_dev_array[i]);
			pollfds[i+1].events = POLLIN;
			pollfds[i+1].revents = 0;
		}

		/* Use ppoll instead poll to avoid poll call reschedules during signal
		 * handling. If we were removing a device, then the uio device's memory
		 * could be freed, but the poll would be rescheduled and end up accessing
		 * the released device. */
		ret = ppoll(pollfds, dev_array_len+1, NULL, NULL);
		if (ret == -1) {
			tcmu_err("ppoll() returned %d, exiting\n", ret);
			exit(EXIT_FAILURE);
		}

		if (pollfds[0].revents) {
			/* If any tcmu devices have been added or removed, the
			   added() and removed() handler callbacks will be called
			   from within this. */
			tcmulib_master_fd_ready(tcmulib_ctx);

			/* Since devices (may) have changed, re-poll() instead of
			   processing per-device fds. */
			continue;
		}

		for (i = 0; i < dev_array_len; i++) {
			if (pollfds[i+1].revents) {
				struct tcmulib_cmd *cmd;
				struct tcmu_device *dev = tcmu_dev_array[i];

				tcmulib_processing_start(dev);

				while ((cmd = tcmulib_get_next_command(dev)) != NULL) {
					ret = foo_handle_cmd(dev,
							     cmd->cdb,
							     cmd->iovec,
							     cmd->iov_cnt,
							     cmd->sense_buf);
					tcmulib_command_complete(dev, cmd, ret);
				}

				tcmulib_processing_complete(dev);
			}
		}
	}

	return 0;
}
コード例 #29
0
void *tx_data_handler(void *arg)
{
  int sock_client = sock_thread[3];
  struct pollfd pfd = {sock_client, POLLIN, 0};
  struct timespec timeout;
  useconds_t delay;
  int result, position, limit, offset;
  ssize_t size, rest;
  char buffer[5003];

  memset(tx_data, 0, 8192);

  limit = 1024;
  rest = 0;

  while(1)
  {
    delay = *tx_rate * 2;

    timeout.tv_sec = 0;
    timeout.tv_nsec = delay * 1000;

    result = ppoll(&pfd, 1, &timeout, NULL);

    if(result < 0) break;

    /* read ram reader position */
    position = *tx_cntr;

    /* receive 4096 bytes if ready, otherwise sleep */
    if((limit > 0 && position > limit) || (limit == 0 && position < 1024))
    {
      offset = limit > 0 ? 0 : 4096;
      limit = limit > 0 ? 0 : 1024;

      if(result == 0)
      {
        memset(tx_data + offset, 0, 4096);
        continue;
      }

      if((size = recv(sock_client, buffer, 4096 + rest, 0)) <= 0) break;

      if(size == 4096 + rest)
      {
        memcpy(tx_data + offset, buffer + rest, 4096);
        rest = 0;
      }
      else
      {
        memset(tx_data + offset, 0, 4096);
        rest = abs(rest - size) & 7;
      }
    }
    else
    {
      usleep(delay);
    }
  }

  memset(tx_data, 0, 8192);

  close(sock_client);
  sock_thread[3] = -1;

  return NULL;
}
コード例 #30
0
ファイル: ring_rawsock.c プロジェクト: AVnu/Open-AVB
// Get a RX frame
U8* ringRawsockGetRxFrame(void *pvRawsock, U32 timeout, unsigned int *offset, unsigned int *len)
{
	AVB_TRACE_ENTRY(AVB_TRACE_RAWSOCK_DETAIL);
	ring_rawsock_t *rawsock = (ring_rawsock_t*)pvRawsock;
	if (!VALID_RX_RAWSOCK(rawsock)) {
		AVB_LOG_ERROR("Getting RX frame; invalid arguments");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}
	if (rawsock->buffersOut >= rawsock->frameCount) {
		AVB_LOG_ERROR("Too many RX buffers in use");
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Get pointer to active buffer in ring
	volatile struct tpacket2_hdr *pHdr =
		(struct tpacket2_hdr*)(rawsock->pMem
							   + (rawsock->blockIndex * rawsock->blockSize)
							   + (rawsock->bufferIndex * rawsock->bufferSize));
	volatile U8 *pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

	AVB_LOGF_VERBOSE("block=%d, buffer=%d, out=%d, pBuffer=%p, pHdr=%p",
					 rawsock->blockIndex, rawsock->bufferIndex, rawsock->buffersOut,
					 pBuffer, pHdr);

	// Check if buffer ready for user
	// In receive mode, we want TP_STATUS_USER flag set
	if ((pHdr->tp_status & TP_STATUS_USER) == 0)
	{
		struct timespec ts, *pts = NULL;
		struct pollfd pfd;

		// Use poll to wait for "ready to read" condition

		// Poll even if our timeout is 0 - to catch the case where
		// kernel is writing to the wrong slot (see below.)
		if (timeout != OPENAVB_RAWSOCK_BLOCK) {
			ts.tv_sec = timeout / MICROSECONDS_PER_SECOND;
			ts.tv_nsec = (timeout % MICROSECONDS_PER_SECOND) * NANOSECONDS_PER_USEC;
			pts = &ts;
		}

		pfd.fd = rawsock->sock;
		pfd.events = POLLIN;
		pfd.revents = 0;

		int ret = ppoll(&pfd, 1, pts, NULL);
		if (ret < 0) {
			if (errno != EINTR) {
				AVB_LOGF_ERROR("Getting RX frame; poll failed: %s", strerror(errno));
			}
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
			return NULL;
		}
		if ((pfd.revents & POLLIN) == 0) {
			// timeout
			AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
			return NULL;
		}

		if ((pHdr->tp_status & TP_STATUS_USER) == 0) {
			// Hmmm, this is unexpected.  poll indicated that the
			// socket was ready to read, but the slot in the TX ring
			// that we're looking for the kernel to fill isn't filled.

			// If there aren't any RX buffers held by the application,
			// we can try to fix this sticky situation...
			if (rawsock->buffersOut == 0) {
				// Scan forward through the RX ring, and look for a
				// buffer that's ready for us to read.  The kernel has
				// a bad habit of not starting at the beginning of the
				// ring when the listener process is restarted.
				int nSkipped = 0;
				while((pHdr->tp_status & TP_STATUS_USER) == 0) {
					// Move to next slot in ring.
					// (Increment buffer/block indexes)
					if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
						rawsock->bufferIndex = 0;
						if (++(rawsock->blockIndex) >= rawsock->blockCount) {
							rawsock->blockIndex = 0;
						}
					}

					// Adjust pHdr, pBuffer to point to the new slot
					pHdr = (struct tpacket2_hdr*)(rawsock->pMem
												  + (rawsock->blockIndex * rawsock->blockSize)
												  + (rawsock->bufferIndex * rawsock->bufferSize));
					pBuffer = (U8*)pHdr + rawsock->bufHdrSize;

					// If we've scanned all the way around the ring, bail out.
					if (++nSkipped > rawsock->frameCount) {
						AVB_LOG_WARNING("Getting RX frame; no frame after poll");
						AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
						return NULL;
					}
				}

				// We found a slot that's ready.  Hopefully, we're good now.
				AVB_LOGF_WARNING("Getting RX frame; skipped %d empty slots (rawsock=%p)", nSkipped, rawsock);
			}
			else {
				AVB_LOG_WARNING("Getting RX frame; no frame after poll");
				AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
				return NULL;
			}
		}
	}

	AVB_LOGF_VERBOSE("Buffer status=0x%4.4lx", (unsigned long)pHdr->tp_status);
	if (pHdr->tp_status & TP_STATUS_COPY) {
		AVB_LOG_WARNING("Frame too big for receive buffer");
	}

	// Check the "losing" flag.  That indicates that the ring is full,
	// and the kernel had to toss some frames. There is no "winning" flag.
	if ((pHdr->tp_status & TP_STATUS_LOSING)) {
		if (!rawsock->bLosing) {
			AVB_LOG_WARNING("Getting RX frame; mmap buffers full");
			rawsock->bLosing = TRUE;
		}
	}
	else {
		rawsock->bLosing = FALSE;
	}

	// increment indexes for next time
	if (++(rawsock->bufferIndex) >= (rawsock->frameCount/rawsock->blockCount)) {
		rawsock->bufferIndex = 0;
		if (++(rawsock->blockIndex) >= rawsock->blockCount) {
			rawsock->blockIndex = 0;
		}
	}

	// Remember that the client has another buffer
	rawsock->buffersOut += 1;

	if (pHdr->tp_snaplen < pHdr->tp_len) {
#if (AVB_LOG_LEVEL >= AVB_LOG_LEVEL_VERBOSE)
		AVB_LOGF_WARNING("Getting RX frame; partial frame ignored (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);
		AVB_LOG_BUFFER(AVB_LOG_LEVEL_VERBOSE, (const U8 *) pBuffer + (pHdr->tp_mac - rawsock->bufHdrSize), pHdr->tp_len, 16);
#else
		IF_LOG_INTERVAL(1000) AVB_LOGF_WARNING("Getting RX frame; partial frame ignored (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);
#endif
		ringRawsockRelRxFrame(rawsock, (U8*)pBuffer);
		AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
		return NULL;
	}

	// Return pointer to the buffer and length
	*offset = pHdr->tp_mac - rawsock->bufHdrSize;
	*len = pHdr->tp_snaplen;
	AVB_LOGF_VERBOSE("Good RX frame (len %d, snaplen %d)", pHdr->tp_len, pHdr->tp_snaplen);

	AVB_TRACE_EXIT(AVB_TRACE_RAWSOCK_DETAIL);
	return (U8*)pBuffer;
}