kevent and unix dgram socket problem
Jason Carroll
jcarroll at gmail.com
Tue Apr 3 12:37:01 UTC 2007
Hi everyone--
I'm working on an application that is attempting to use kqueues to
detect data arriving at a unix domain datagram socket, but kevents
don't appear to get delivered when a datagram arrives. Using poll()
for the same purpose appears to work fine. Also, if I switch the
socket to the AF_INET domain, I see the correct behavior with
kevent().
I distilled the problem into two files that I included. listen.cc
creates a unix socket and blocks for data on a kevent() call.
write.cc sends a brief message to the same unix socket.
I've seen the problem on 6-STABLE and 4.5-RELEASE.
Anyone have any thoughts or comments?
Thanks,
Jason
// ================ listen.cc =================
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <string.h>
#include <sys/filio.h>
#include <sys/event.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <stdio.h>
#include <assert.h>
#include <poll.h>
#define LISTENQ 2
#define UN_PATH_LEN sizeof(((struct sockaddr_un*)0)->sun_path)
int main(int argc, char *argv[])
{
// new socket
int fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
assert(fd >= 0);
// make sure there isn't something in it's way
unlink("usock");
// create the local address, bind & listen
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_LOCAL;
strncpy(addr.sun_path, "usock", UN_PATH_LEN - 1);
assert(bind(fd, (sockaddr*) &addr, sizeof(sockaddr_un)) == 0);
assert(listen(fd, LISTENQ) == 0);
char buf[1024];
int nread;
// uncomment this line to prove my socket is set up correctly
// nread = read(fd, buf, sizeof(buf));
// printf("read %d bytes\n", nread);
int kqueueFD;
kqueueFD = kqueue();
struct kevent event;
EV_SET(&event, fd, EVFILT_READ, EV_ADD, 0, 0, 0);
assert(kevent(kqueueFD, &event, 1, 0, 0, 0) == 0);
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
pfd.revents = 0;
int r;
// uncomment the following two lines to see poll behavior
// while ((r = poll(&pfd, 1, INFTIM)) >= 0) {
// printf("poll returned %d\n", r);
// uncomment the following two lines to see kqueue behavior
while ((r = kevent(kqueueFD, 0, 0, &event, 1, 0)) >= 0) {
printf("kevent returned %d\n", r);
nread = read(fd, buf, sizeof(buf));
printf("read %d bytes\n", nread);
}
}
// ================ write.cc =================
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <string.h>
#include <sys/filio.h>
#include <sys/event.h>
#include <sys/types.h>
#include <net/if.h>
#include <sys/sockio.h>
#include <stdio.h>
#include <assert.h>
#define LISTENQ 2
#define UN_PATH_LEN sizeof(((struct sockaddr_un*)0)->sun_path)
int main(int argc, char *argv[])
{
int fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
assert(fd >= 0);
// create the local address & "connect"
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_LOCAL;
strncpy(addr.sun_path, "usock", UN_PATH_LEN - 1);
assert(connect(fd, (sockaddr*) &addr, sizeof(sockaddr_un)) == 0);
const char *msg = "this is the message\n";
write(fd, msg, strlen(msg));
}
More information about the freebsd-hackers
mailing list