1

I have the following libev code:

#include <ev.h>
#include <stdio.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <string.h>
#include <stdlib.h>
#include <sys/un.h>
#include <netinet/in.h>

ev_io stdin_watcher;

static void cb(EV_P_ ev_io *w, int revents){
        puts ("hello");

        //read file here - suggestion due to Ioan
        #define BUF_LEN 10
        char buf[BUF_LEN];
        memset(buf,0,BUF_LEN);
        int byte_read;
        while( (byte_read = recv(w->fd,buf,BUF_LEN-1,0)) > 0) {
                printf("len: %i: %s",byte_read,buf);
                memset(buf,0,BUF_LEN);
        }


        if(-1 == byte_read && EAGAIN != errno) {
            perror("recv");
        }
        close(w->fd);

        //ev_io_stop (EV_A_ w);
        //ev_unloop (EV_A_ EVUNLOOP_ALL);
}


int main (void){
        struct ev_loop *loop = ev_default_loop (0);
        int len;

        int sd;
        sd=socket(AF_UNIX,SOCK_STREAM,0);

        struct sockaddr_un address;
        //memset(&address,0,sizeof(address));
        address.sun_family=AF_UNIX;
        strcpy(address.sun_path,"/tmp/mysocket");
        unlink(address.sun_path);
        len=strlen(address.sun_path)+sizeof(address.sun_family);

        int x=bind(sd,(struct sockaddr*)&address,sizeof(address));
        printf("%d\n",x);
        listen(sd,5);

        ev_io_init(&stdin_watcher,cb,sd,EV_READ);
        ev_io_start(loop,&stdin_watcher);

        ev_loop (loop, 0);

        // unloop was called, so exit
        return 0;
}

Everything works just fine (almost). Compile: gcc file.c -lev, and run ./a.out. Then write to the socket that ./a.out is listening on: echo "gobblydeegook" | nc -U /tmp/mysocket.

Hello appears on the console as expected.

But the program calls the event and then it keeps printing "hello" ad-infinitum! I want it to continue monitoring this unix socket for writes. How to do this?

Eamorr
  • 9,872
  • 34
  • 125
  • 209

1 Answers1

2

The event gets called when there is data to be read on the socket. Since you aren't removing the data from the socket, just printing "hello", the event is called again for you to handle the data.

Ioan
  • 2,382
  • 18
  • 32
  • Mmm. That's very interesting thanks. I've tried to read the data (see updated post, but I keep getting a "recv: Invalid argument" error. – Eamorr Jan 27 '12 at 15:35
  • libev also calls the same event for errors on the socket, like when it's closed. Since you close the socket, the event is called again, at which point, you try to recv on a closed socket. – Ioan Jan 27 '12 at 15:39
  • oh right... I think I'm understanding you. Do you know any way to counteract against this? – Eamorr Jan 27 '12 at 15:41
  • 1
    Check docs for recv and handle the case of a closed socket. Better yet, stop the watcher if you close the socket. – Ioan Jan 27 '12 at 15:45
  • 1
    Also, check the docs for libev IO events. Once a socket is closed, the descriptor becomes invalid and could result in errors if the same one is reused unknowingly. – Ioan Jan 27 '12 at 15:46