0

I trying to set up two daemons, a client and a server, the server profiles some system statistics, and waits in a non blocking manner for a SIGIO to be received, upon which it will read the data sent to it, send something back to the client and continue onwards with whatever it was doing.

The client however issues blocking send and receive functions on its socket. I have done quite a bit of coding, and read extensively, but it appears there are a lot of different paradigms that people use when trying to achieve this kind of behaviour, I would really appreciate some help, here is my code so far:

SERVER:

  int s, s2, flags, n;
  struct sockaddr_un addr;
  struct sockaddr_un from;
  int from_len;
  socklen_t len;

  void message_received_helper(int sig){
  syslog(LOG_NOTICE, "Works! \n");
  }

  ...

    int main(int argc, char *argv[]) {

    deamonize();

    /* Daemon-specific initialization goes here */
setlogmask (LOG_UPTO (LOG_NOTICE));

openlog ("i_aware", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);

    syslog (LOG_NOTICE, "Program started by User %d", getuid ());

/*
 * This set up is for the non blocking socket that will exist on the server
 */
/* specify the new action for the SIGIO signal */
new_action.sa_handler = message_received_helper;
/* supply the empty set to .sa_mask */
sigemptyset(&new_action.sa_mask);
/* no flags*/
new_action.sa_flags = 0;
/* Associate new_action with the signal SIGIO -
 NULL indicates we are not saving any previous action*/
if(sigaction(SIGIO, &new_action, NULL) < 0 ){
    syslog(LOG_NOTICE, "Could not associate SIGIO with action...\n");
    exit(errno);
}

/*TODO create unix domain socket and listen for a connection*/
if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 ){
    syslog(LOG_NOTICE, "Could not create socket: %d \n", errno);
    perror("socket");
    exit(errno);

}

/* bind socket */
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/dev/foo");
unlink(addr.sun_path);
len = (socklen_t) (strlen(addr.sun_path) + sizeof(addr.sun_family));

if( bind(s, (struct sockaddr *) &addr,len ) == -1){
    syslog(LOG_NOTICE, "Could not bind socket %d \n", errno);
    perror("bind");
    exit(errno);

}
/* listen */
if(listen(s, 1) < 0){
    syslog(LOG_NOTICE,"Error on listen: %d \n", errno);
    perror("listen");
    exit(errno);        

}
from_len = sizeof(from);
if(s2 = accept(s,  (struct sockaddr *) &from, &from_len ) < 0 ){
    syslog(LOG_NOTICE,"Error on accept: %d \n", errno);
    perror("accept");
    exit(errno);

}
syslog(LOG_NOTICE,"success \n");

/* set the ownership of the socket fd to this process */
syslog(LOG_NOTICE, "F_SETOWN: %d \n" ,fcntl(s2, F_SETOWN, getpid()) );  
/*get file access mode and file status flag - no args needed for this F_GETFL comand*/
flags  = fcntl(s2, F_GETFL);
syslog(LOG_NOTICE, "F_GETFL: %d \n", flags);
/* Enable non blocking */
syslog(LOG_NOTICE, "F_SETFL: %d \n" , fcntl(s2, F_SETFL, flags | FASYNC));

/*
 * At this point the socket described by s2, should be a non blocking socket, when a SIGIO
 * is raised upon receipt of data waiting on the socket the method message_received_helper
 * will be called 
 */ 
n = recv(s2, str, 1, 0);
syslog(LOG_NOTICE, "Works! \n");

if (n <= 0) {
           if (n < 0) syslog(LOG_NOTICE, "recv error: %d", errno);
        }
        syslog(LOG_NOTICE, "n: %d, s2: %d, str: %s \n", n, s2, str );


    if (send(s2, str, n, 0) < 0) {
            syslog(LOG_NOTICE, "send: %d", errno);

            }

CLIENT:

int s, s2, t, len;
struct sockaddr_un local, remote;
char str[100];

if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
}

local.sun_family = AF_UNIX;
strcpy(local.sun_path, SOCK_PATH);
unlink(local.sun_path);
len = strlen(local.sun_path) + sizeof(local.sun_family);
if (bind(s, (struct sockaddr *)&local, len) == -1) {
    perror("bind");
    exit(1);
}

if (listen(s, 5) == -1) {
    perror("listen");
    exit(1);
}

for(;;) {
    int done, n;
    printf("Waiting for a connection...\n");
    t = sizeof(remote);
    if ((s2 = accept(s, (struct sockaddr *)&remote, &t)) == -1) {
        perror("accept");
        exit(1);
    }

    printf("Connected.\n");

    done = 0;
    do {
        n = recv(s2, str, 100, 0);
        if (n <= 0) {
            if (n < 0) perror("recv");
            done = 1;
        }

        if (!done) 
            if (send(s2, str, n, 0) < 0) {
                perror("send");
                done = 1;
            }
    } while (!done);

    close(s2);

The two processes are able to connect over the socket, but no SIGIO is raised when the client sends data to the server. Also the recv() function keeps blocking, as though nothing I did affected the socket s2 to make reads non blocking.

2
  • How is this Ubuntu related?
    – guntbert
    Mar 19, 2013 at 21:03
  • I am attempting to perform all this asynchronous IPC on a Linux distribution called Ubuntu. Anyhow I figured it out and will close the question.
    – Radagasp
    Mar 19, 2013 at 21:25

1 Answer 1

2
if(s2 = accept(s,  (struct sockaddr *) &from, &from_len ) < 0 ) 

is incorrect, it should read

if( (s2 = accept(s,  (struct sockaddr *) &from, &from_len )) < 0 )

The missing parentheses made the first statement read s2 = < 0, which set s2 to 0;

Not the answer you're looking for? Browse other questions tagged .