Skip to content

Instantly share code, notes, and snippets.

@depressed-pho
Last active December 14, 2015 23:59
Show Gist options
  • Save depressed-pho/5169980 to your computer and use it in GitHub Desktop.
Save depressed-pho/5169980 to your computer and use it in GitHub Desktop.
kqueue-poll-select
% uname -a
FreeBSD nem.cielonegro.org 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #0: Tue Jan 5 16:02:27 UTC 2010 [email protected]:/usr/obj/usr/src/sys/GENERIC i386
% ./kqueue-poll-select
Testing stdin...
Type of stdin: tty
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdin.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: tty
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdout.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% touch empty
% ./kqueue-poll-select < /dev/random > empty
Testing stdin...
Type of stdin: device
Checking if kqueue(2) works...
kevent(2) ifself succeeded but delivered us an EV_ERROR. This is how the old I/O
manager was fooled because it wasn't (and the newer one still don't) check this situation: Operation not supported by device
kevent(2) expectedly failed now. This time we didn't pass a non-NULL incoming event buffer. This is how the new I/O manager fails on this platform: Operation not supported by device
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: regular
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdout.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
/*
* This is a test program to see if kqueue/poll/select can handle your
* stdin.
*
* compile:
* % g++ -o kqueue-poll-select kqueue-poll-select.cpp
*
* run:
* % ./kqueue-poll-select < WHATEVER-FILE-YOU-WANT-TO-TEST
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#if !defined(__gnu_linux__)
#include <sys/event.h>
#endif
#include <sys/time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>
#include <sys/select.h>
#include <err.h>
void test_fd(int fd, const char* name, bool reading) {
/* Determine the type of fd */
struct stat st;
if (fstat(fd, &st) < 0) {
err(1, name);
}
const char* type;
switch (st.st_mode & S_IFMT) {
case S_IFIFO:
type = "fifo";
break;
case S_IFCHR:
if (isatty(fd)) {
type = "tty";
}
else {
type = "device";
}
break;
case S_IFREG:
type = "regular";
break;
case S_IFSOCK:
type = "socket";
break;
default:
type = "unknown";
break;
}
fprintf(stderr, "Type of %s: %s\n", name, type);
#if !defined(__gnu_linux__)
fprintf(stderr, "\nChecking if kqueue(2) works...\n");
int kq = kqueue();
if (kq < 0) {
fprintf(stderr, "kqueue(2) somehow failed. This should not happen: %s\n", strerror(errno));
}
else {
struct kevent change;
EV_SET(&change, fd, (reading ? EVFILT_READ : EVFILT_WRITE), EV_ADD, 0, 0, NULL);
struct timespec timeout;
timeout.tv_sec = 0;
timeout.tv_nsec = 0;
struct kevent event;
if (kevent(kq, &change, 1, &event, 1, &timeout) < 0) {
fprintf(stderr, "kevent(2) somehow failed even though we passed a non-NULL"
" incoming event buffer. This should not happen: %s\n", strerror(errno));
}
else if (event.flags & EV_ERROR) {
errno = event.data;
fprintf(stderr, "kevent(2) ifself succeeded but delivered us an EV_ERROR."
" This is how the old I/O manager was fooled because it wasn't"
" (and the newer one still don't) check this situation: %s\n", strerror(errno));
if (kevent(kq, &change, 1, NULL, 0, &timeout) < 0) {
fprintf(stderr, "kevent(2) expectedly failed now. This time we didn't pass a"
" non-NULL incoming event buffer. This is how the new I/O"
" manager fails on this platform: %s\n", strerror(errno));
}
else {
fprintf(stderr, "kevent(2) somehow succeeded now. Why?: %s\n", strerror(errno));
}
}
else {
fprintf(stderr, "Great. kevent(2) successfully handled your %s.\n", name);
}
}
#endif
fprintf(stderr, "\nChecking if poll(2) works...\n");
struct pollfd pfd;
pfd.fd = fd;
pfd.events = (reading ? POLLIN : POLLOUT);
if (poll(&pfd, 1, 0) < 0) {
fprintf(stderr, "poll(2) somehow failed. This should not happen: %s\n", strerror(errno));
}
else if (pfd.revents == POLLIN || pfd.revents == POLLOUT || pfd.revents == 0) {
fprintf(stderr, "Good. poll(2) successfully handled your %s.\n", name);
}
else if (pfd.revents == POLLNVAL) {
fprintf(stderr, "poll(2) itself succeeded but delivered us a POLLNVAL event."
" It can't handle your %s.\n", name);
}
else {
fprintf(stderr, "poll(2) itself succeeded but delivered us an unknown event."
" It seems poll(2) can't handle your %s: %d\n", name, (int)pfd.revents);
}
fprintf(stderr, "\nChecking if select(2) works...\n");
fd_set rfd;
fd_set wfd;
FD_ZERO(&rfd);
FD_ZERO(&wfd);
if (reading) {
FD_SET(fd, &rfd);
}
else {
FD_SET(fd, &wfd);
}
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
if (select(fd + 1, &rfd, &wfd, NULL, &timeout) < 0) {
fprintf(stderr, "select(2) can't handle your %s. This is terrible...:", name, strerror(errno));
}
else {
fprintf(stderr, "OK. select(2) successfully handled your %s.\n", name);
}
}
int main() {
fprintf(stderr, "Testing stdin...\n");
test_fd(STDIN_FILENO , "stdin" , true );
fprintf(stderr, "\nTesting stdout...\n");
test_fd(STDOUT_FILENO, "stdout", false);
return 0;
}
% uname -a
Darwin aria.cielonegro.org 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu-1228.15.4~1/RELEASE_PPC Power Macintosh
% ./kqueue-poll-select
Testing stdin...
Type of stdin: tty
Checking if kqueue(2) works...
kevent(2) ifself succeeded but delivered us an EV_ERROR. This is how the old I/O
manager was fooled because it wasn't (and the newer one still don't) check this
situation: Operation not supported
kevent(2) expectedly failed now. This time we didn't pass a non-NULL incoming ev
ent buffer. This is how the new I/O manager fails on this platform: Operation no
t supported
Checking if poll(2) works...
poll(2) itself succeeded but delivered us a POLLNVAL event. It can't handle your
stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: tty
Checking if kqueue(2) works...
kevent(2) ifself succeeded but delivered us an EV_ERROR. This is how the old I/O manager was fooled because it wasn't (and the newer one still don't) check this situation: Operation not supported
kevent(2) expectedly failed now. This time we didn't pass a non-NULL incoming event buffer. This is how the new I/O manager fails on this platform: Operation not supported
Checking if poll(2) works...
poll(2) itself succeeded but delivered us a POLLNVAL event. It can't handle your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% touch empty
% ./kqueue-poll-select < empty > empty
Testing stdin...
Type of stdin: regular
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdin.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: regular
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdout.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% uname -a
Linux boss 2.6.16.27-0.6-smp #1 SMP Wed Dec 13 09:34:50 UTC 2006 x86_64 x86_64 x86_64 GNU/Linux
% ./kqueue-poll-select
Testing stdin...
Type of stdin: tty
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: tty
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% touch empty
% ./kqueue-poll-select < /dev/random > empty
Testing stdin...
Type of stdin: device
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: regular
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% uname -a
NetBSD seras 6.99.17 NetBSD 6.99.17 (VMWARE) #1: Fri Feb 15 13:06:57 JST 2013 pho@seras:/usr/obj/sys/arch/amd64/compile/VMWARE amd64
% ./kqueue-poll-select
Testing stdin...
Type of stdin: tty
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdin.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: tty
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdout.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
% touch empty
% ./kqueue-poll-select < /dev/random > empty
Testing stdin...
Type of stdin: device
Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdin.
Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.
Checking if select(2) works...
OK. select(2) successfully handled your stdin.
Testing stdout...
Type of stdout: regular
Checking if kqueue(2) works...
kevent(2) ifself succeeded but delivered us an EV_ERROR. This is how the old I/O manager was fooled because it wasn't (and the newer one still don't) check this situation: Invalid argument
kevent(2) expectedly failed now. This time we didn't pass a non-NULL incoming event buffer. This is how the new I/O manager fails on this platform: Invalid argument
Checking if poll(2) works...
Good. poll(2) successfully handled your stdout.
Checking if select(2) works...
OK. select(2) successfully handled your stdout.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment