How to use sigmask in order to make signals can be processed by a thread

Hi,

I have a UDP server and client program, and they must run within a program, so I decided two threads, one for UDP server and another for UDP client.

The simple architecture is shown in attachment.

However, I can't send the packets out on the UDP client, no any time message and sigaction is triggered. Is any sigmask needs? If it is, then where should I put the mask?

The following are the source codes

The UDP server

static void SIGIOHandler( int signalType ) {
    struct sockaddr_in clntAddr;
    unsigned int clntLen;
    int recvMsgSize;
    UINT8 buf[ MSG_SIZE ];
    do {
        clntLen = sizeof( clntAddr );
        if ( ( recvMsgSize = recvfrom( srvSock, buf, MSG_SIZE, 0, ( struct sockaddr* )&clntAddr,&clntLen ) ) < 0 ) {
            if ( errno != EWOULDBLOCK ) {
                      ...Error handler
            }
        } else {
            printf( "Handling client %s\n", inet_ntoa( clntAddr.sin_addr ) );
            if ( Sendto( srvSock, buf, recvMsgSize, 0, ( struct sockaddr* )&clntAddr, sizeof( clntAddr ),
            __FILE__, __LINE__ ) != recvMsgSize ) {
               ...Error handler
            }
        }
    }  while ( recvMsgSize >= 0 );
    printf( "%s completed\n", inet_ntoa( clntAddr.sin_addr ) );
}


void Server_Constructor () {
    char buf[ 128 ];
    struct sockaddr_in echoServAddr;
    struct sigaction handler;

    /* Initiating socket. */
    srvSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
    memset( &echoServAddr, 0, sizeof( echoServAddr ) );
    echoServAddr.sin_family = AF_INET;
    echoServAddr.sin_addr.s_addr = htonl( INADDR_ANY );
    echoServAddr.sin_port = htons( ( unsigned short )23456 );
    Bind( srvSock, ( struct sockaddr* )&echoServAddr, sizeof( echoServAddr ) );

    /* Initiating signal handler. */
    handler.sa_handler = SIGIOHandler;
    if ( sigfillset( &handler.sa_mask ) < 0 ) {
      ...Error handler
    }
    handler.sa_flags = 0;   /* No flags */
    if ( sigaction( SIGIO, &handler, 0 ) < 0 ) {
      ...Error handler
    }
    if ( fcntl( srvSock, F_SETOWN, getpid() ) < 0 ) {
      ...Error handler
    }
    if ( fcntl ( srvSock, F_SETFL, O_NONBLOCK | FASYNC ) < 0 ) {
      ...Error handler
    }

    /* Wait forever. */
   ....
}

The UDP client

static void CatchAlarm ( int ignored ) {
    tries += 1;
}

void Client_Sendto ( const struct sockaddr* dest_addr, const void* message ) {
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr; /* Echo server address */
    struct sockaddr_in fromAddr;     /* Source address of echo */
    unsigned int fromSize;           /* In-out of address size for recvfrom() */
    struct sigaction myAction;       /* For setting signal handler */
    char *servIP;                    /* IP address of server */
    char echoString[ MSG_SIZE ] = "123";                /* String to send to echo server */
    char recvbuf[ MSG_SIZE ];
    int respStringLen;               /* Size of received datagram */

    servIP = "127.0.0.1";           /* First arg:  server IP address (dotted quad) */

    sock = Socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP, __FILE__, __LINE__ );

    /* Set signal handler for alarm signal */
    myAction.sa_handler = CatchAlarm;
    if (sigfillset(&myAction.sa_mask) < 0) /* block everything in handler */
        DieWithError("sigfillset() failed");
    myAction.sa_flags = 0;

    if (sigaction(SIGALRM, &myAction, 0) < 0)
        DieWithError("sigaction() failed for SIGALRM");

    /* Construct the server address structure */
    memset(&echoServAddr, 0, sizeof(echoServAddr));    /* Zero out structure */
    echoServAddr.sin_family = AF_INET;
    echoServAddr.sin_addr.s_addr = inet_addr(servIP);  /* Server IP address */
    echoServAddr.sin_port = htons( ( unsigned short )UDP_PORT );       /* Server port */

The UDP client unable send packet out, I think it can't receive the signal in the thread, so how to do that? 

    /* Send the string to the server */
    if (sendto(sock, echoString, MSG_SIZE, 0, (struct sockaddr *)
               &echoServAddr, sizeof(echoServAddr)) != MSG_SIZE)
        DieWithError("sendto() sent a different number of bytes than expected");

    /* Get a response */
    fromSize = sizeof( fromAddr );
    alarm( TIMEOUT_SECS );  /* Set the timeout */
    while ((respStringLen = recvfrom(sock, recvbuf, MSG_SIZE, 0,
           (struct sockaddr *) &fromAddr, &fromSize)) < 0)
        if (errno == EINTR)     /* Alarm went off  */
        {
            if (tries < MAXTRIES)      /* incremented by signal handler */
            {
                printf("timed out, %d more tries...\n", MAXTRIES-tries);
                if (sendto(sock, echoString, MSG_SIZE, 0, (struct sockaddr *)
                            &echoServAddr, sizeof(echoServAddr)) != MSG_SIZE)
                    DieWithError("sendto() failed");
                alarm(TIMEOUT_SECS);
            }
            else
                DieWithError("No Response");
        }
        else
            DieWithError("recvfrom() failed");
    alarm( 0 ); /* Cancel the timeout. */
    Close( sock, __FILE__, __LINE__ );
    printf( "Received: %s\n", recvbuf );    /* Print the received data */
}


static void* SENDER ( void* null ) {
    do {
        Client_Sendto( NULL, NULL );
        sleep( 1 );
    } while ( 1 );
    return NULL;
}


void Client_DebugThread () {
    pthread_t tid;              /* Thread ID. */
    pthread_attr_t rx;          /* Parameter of thread. */
    pthread_attr_init( &rx );   /* Free resources immediately if a thread is terminated. */
    pthread_attr_setdetachstate( &rx, PTHREAD_CREATE_DETACHED );
    pthread_create( &tid, &rx, SENDER, NULL, __FILE__, __LINE__ ); 
}

First, never, ever, ever make calls like "printf()" within a signal handler. The only system calls you can safely make from within a signal handler are those listes as async-signal safe. On Linux. see the man page for "signal" for a list.

Calling a non-async-signal-safe call from within a signal handler results in "undefined" behavior. In practice that usually means a deadlock because your signal handler will attempt to acquire a lock already held by the thread that the signal interrupted.

Second, don't call sigfillset() on your sigaction structure. If anything, call sigemptyset().

Worse, you can't even count on being able to safely set the value of a variable in a signal handler unless it can be done atomically (such as with volatile sig_atomic_t). You really want to do as little as possible in a sighandler. If possible, set an atomic flag and get out.

Regards,
Alister