Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Apr 2007 08:10:55 -0400
From:      "Jason Carroll" <jcarroll@gmail.com>
To:        freebsd-hackers@freebsd.org
Subject:   kevent and unix dgram socket problem
Message-ID:  <da4a53d80704030510r32aa98eek4e7b01fb781ea205@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
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));
}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?da4a53d80704030510r32aa98eek4e7b01fb781ea205>