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));
}
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to