I want to use a single thread to process socket incoming data and do some actions when the semaphore gets unlocked. According to this thread
Can we obtain a file descriptor for a semaphore or condition variable?
I can't use the select system call for this. Now I'm trying something like this using signals instead of select(). But I can't get rid of possible race conditions.
static int dataReady; // Socket data ready flag
static int fd; // Socket file descriptor
static int32* pldSemId; // Semaphore identifier
void sigioHandler(int /* sig */){
dataReady = 1;
}
void tryReceiveData(){
disableSignals();
int len;
char buf[8192];
struct sockaddr_nl sourceaddr;
struct iovec iov = { buf, sizeof(buf) };
struct msghdr msg;
struct nlmsghdr *nh;
if (!dataReady){
enableSignals();
return;
}
msg = { &sourceaddr, sizeof(sourceaddr), &iov, 1, NULL, 0, 0 };
len = recvmsg(fd, &msg, MSG_DONTWAIT);
...
dataReady = 0;
enableSignals();
}
void doSemaphoreActions(){
int r;
sops.sem_num = 0;
sops.sem_op = -1;
sops.sem_flg = 0; // wait and blocked
if (semop(*pldSemId, &sops, 1) == -1) {
if (errno == EINTR){
return;
}
// Process other possible errors
...
}
// Do something useful
...
}
int main(){
// Open and configure the socket
fd = socket(...);
...
// Configure the signal handler
signal(SIGIO, sigioHandler);
fcntl(fd, F_SETOWN, getpid());
fcntl(fd, F_SETFL, O_ASYNC);
// Configure the semaphore
...
while (true){
tryReceiveData();
// SIGIO signal may be received here so we won't
// process socket data until the next SIGIO arrives
// or the semaphore gets unlocked
doSemaphoreActions();
}
}
Is there a way to disable signal handlers when the thread is in the "running" state? Or maybe there is a better solution?