I am learning how to use pselect. I took an example code which worked fine and modified it to call the same code from a thread which is spawned from main and it does not work (pselect remains blocked forever)
#include <sys/select.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
/* Flag that tells the daemon to exit. */
static volatile int exit_request = 0;
/* Signal handler. */
static void hdl (int sig)
{
exit_request = 1;
printf("sig=%d\n", sig);
}
/* Accept client on listening socket lfd and close the connection
* immediatelly. */
static void handle_client (int lfd)
{
int sock = accept (lfd, NULL, 0);
if (sock < 0) {
perror ("accept");
exit (1);
}
puts ("accepted client");
close (sock);
}
void *mythread(void *arg __attribute__ ((unused)))
{
int lfd;
struct sockaddr_in myaddr;
int yes = 1;
sigset_t mask;
sigset_t orig_mask;
struct sigaction act;
memset (&act, 0, sizeof(act));
act.sa_handler = hdl;
/* This server should shut down on SIGUSR1. */
if (sigaction(SIGUSR1, &act, 0)) {
perror ("sigaction");
return NULL;
}
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);
if (pthread_sigmask(SIG_BLOCK, &mask, &orig_mask) < 0) {
perror ("pthread_sigmask");
return NULL;
}
lfd = socket (AF_INET, SOCK_STREAM, 0);
if (lfd < 0) {
perror ("socket");
return NULL;
}
if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR,
&yes, sizeof(int)) == -1) {
perror ("setsockopt");
return NULL;
}
memset (&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = INADDR_ANY;
myaddr.sin_port = htons (10000);
if (bind(lfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
perror ("bind");
return NULL;
}
if (listen(lfd, 5) < 0) {
perror ("listen");
return NULL;
}
while (!exit_request) {
fd_set fds;
int res;
/* BANG! we can get SIGUSR1 at this point, but it will be
* delivered while we are in pselect(), because now
* we block SIGUSR1.
*/
FD_ZERO (&fds);
FD_SET (lfd, &fds);
res = pselect (lfd + 1, &fds, NULL, NULL, NULL, &orig_mask);
if (res < 0 && errno != EINTR) {
perror ("select");
return NULL;
}
else if (exit_request) {
puts ("exited");
break;
}
else if (res == 0)
continue;
if (FD_ISSET(lfd, &fds)) {
handle_client (lfd);
}
}
return NULL;
}
int main (int argc, char *argv[])
{
void * res;
pthread_t mythr_h;
pthread_create(&mythr_h, (pthread_attr_t *)NULL, mythread, NULL);
pthread_join(mythr_h, &res);
return 0;
}
strong text
After sending SIGUSR1 to this program I see that it remains blocked in the pselect call. When the code in mythread function is moved back into main and not spawning any thread from main, it works perfectly.