I am doing a test setup where I use UNIX signals for communication.The following code uses SIGUSR1 and SIGUSR2 to transfer a string from a client process to a server process that will listen for incoming signals. I know this is not how signals should be used and I kindly ask you to disregard any "that function is not signal-safe", because in this test setup the client will wait for the server to acknowledge each received bit via a signal back to the client which will in turn as answer to that signal send the next bit to the server.This way no signal should interrupt while a signal is being handled. Or so I think at least... I am not sure on anything right now anymore...
The problem is that I suddenly receive signals from pid 0 (which is broadcast?) but I never send a broadcast. The code will work for smaller strings but getting larger (~100 chars) it will sometimes work and sometimes not. I could deal with this situation by just sending->sleep->sending in the client, which would be slower but I am really interested in what is going on here.
Here is the server code:
void sig_handler(int _signum, siginfo_t *_info, void *_context){ static unsigned char str[MAX_MSG_SIZE]; static int str_i; t_bool done; int i; if (_info->si_pid != 0) { if (((str_i++) * 0) || _signum == SIGUSR2) str[(str_i - 1) / 8] |= 1 << (7 - (((str_i - 1) % 8))); done = !(str_i % 8) && !str[(str_i / 8) - 1]; if (done) { i = ((str_i / 8 - 4) >= 0) * (str_i / 8 - 4)+ ((str_i / 8 - 4) < 0) * -1;//this saves a line... while (++i < str_i / 8) if (str[i] == 0xf0) done = FALSE; } if ((str_i / 8 == MAX_MSG_SIZE || done) && _info->si_pid != 0) { ft_printf("kill\n"); write(1, str, str_i / 8); ft_memset(str, 0, MAX_MSG_SIZE); str_i = 0; kill(_info->si_pid, SIGUSR2); } else if (_info->si_pid != 0) kill(_info->si_pid, SIGUSR1); else ft_printf("wtf"); } else ft_printf("\nOH WTF IS HAPPENING\n");}int main(void){ struct sigaction sa; ft_printf("%d\n", getpid()); sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGUSR1); sigaddset(&sa.sa_mask, SIGUSR2); sa.sa_sigaction = sig_handler; sa.sa_flags = SA_RESTART | SA_SIGINFO; if (sigaction(SIGUSR1, &sa, NULL) == -1 || sigaction(SIGUSR2, &sa, NULL) == -1) return (0); while (TRUE) sleep(10000); return (0);}
Notice i added allot of print statements to find out what is happening.here is the client:
typedef struct s_client_info{ int pid; char *str; int i; t_bool run;} t_client_info;void sig_handler(int _signum, siginfo_t *_info, void *_context){ static t_client_info *v; //usleep(200); if (_info && !_info->si_pid) //this prints 0-n times randomly at any moment ft_printf("wtf"); if (!_signum && !_info) //setup { v = _context; v->run = TRUE; } if (_signum == SIGUSR2 || !v->run) //received stop signal from server { v->run = FALSE; return ; } if (v->pid == 0) //is never called ft_printf("Wtf1"); if ((v->str[v->i / 8] << (v->i % 8)) & 0b10000000) //extracts current bit kill(v->pid, SIGUSR2); //send '1' to server else kill(v->pid, SIGUSR1); //send '0' to server v->i++;}int main(int _argc, char *_argv[]){ t_client_info v; struct sigaction sa; int i;//check input i = -1; while (_argv[1][++i]) if (_argv[1][i] < '0' || _argv[1][i] > '9') return (print_usage(), 0); if (_argc != 3) return (print_usage(), 0);//prepare client info v.pid = ft_atoi(_argv[1]); v.str = _argv[2]; v.i = 0;//register signal handler sa.sa_flags = SA_SIGINFO; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGUSR1); sigaddset(&sa.sa_mask, SIGUSR2); sa.sa_sigaction = sig_handler; if (sigaction(SIGUSR1, &sa, NULL) == -1 || sigaction(SIGUSR2, &sa, NULL) == -1) return (0);//start sending sig_handler(0, NULL, &v); while (v.run) usleep(10); return (0);}
If I uncomment that usleep, the communication will work, but the client will still sometimes receive a signal from pid 0 and print "wtf"
I thought maybe another process is sending a broadcast randomly, so i set up an extra process that checks for that... nope there is no other process. somehow one of these or both end up sending a malformed signal.
This is some output from the server. After receiving the same message for a 3. time it will fail and never send the stop signal(SIGUSR2) to the client
😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuhkill😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh
OH WTF IS HAPPENING
I needed to stop the client manually at this point.
So I added this in the client and enabled the usleep again to check whether the weird pid = 0 signals come in at some specific time:
if ((v->str[v->i / 8] << (v->i % 8)) & 0b10000000) ft_printf("1"),kill(v->pid, SIGUSR2); else ft_printf("0"),kill(v->pid, SIGUSR1);
And they just drop in randomly. here is an example:
./client 19863😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh😀wiegyhweoufgiaqefouhqaefouhqofsuh111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001110110100101100001011100010110010101100110011011110111010101101000011100010110000101100101011001100110111101110101011010000111000101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110111101110101011001100110011101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110001011011110110011001110011011101010110100011110000100111111001100010000000011101110110100101100101011001110111100101101000011101110110010101101111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100110011100110111010101101000111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001110110100101100001011100010110010101100110011011110111010101101000011100010110000101100101011001100110111101110101011010000111000101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110111101110101011001100110011101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110wtf00101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110111101110101011001100110011101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110001011011110110011001110011011101010110100011110000100111111001100010000000011101110110100101100101011001110111100101101000011101110110010101101111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100110011100110111010101101000111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001110110100101100001011100010110010101100110011011110111010101101000011100010110000101100101011001100110111101110101011010000111000101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110111101110101011001100110011101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110001011011110110011001110011011101010110100011110000100111111001100010000000011101110110100101100101011001110111100101101000011101110110010101101111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100110011100110111010101101000111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001110110100101100001011100010110010101100110011011110111010101101000011100010110000101100101011001100110111101110101011010000111000101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110111101110101011001100110011101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110001011011110110011001110011011101010110100011110000100111111001100010000000011101110110100101100101011001110111100101101000011101110110010101101111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100110011100110111010101101000111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001110110100101100001011100010110010101100110011011110111010101101000011100010110000101100101011001100110111101110101011010000111000101101111011001100111001101110101011010001111000010011111100110001000000001110111011010010110010101100111011110010110100001110111011001010110wtf1111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100110011100110111010101101000111100001001111110011000100000000111011101101001011001010110011101111001011010000111011101100101011011110111010101100110011001wtf1101101001011000010111000101100101011001100110111101110101011010000111000101100001011001010110011001101111011101010110100001110001011011110110011001110011011101010110100011110000100111111001100010000000011101110110100101100101011001110111100101101000011101110110010101101111011101010110011001100111011010010110000101110001011001010110011001101111011101010110100001110001011000010110010101100110011011110111010101101000011100010110111101100wtf11001110011011101010110100000000000
here is another screenshot of a run without the usleep in client:
Server left, Client right.After that I send a small message to the server without restarting it and it suddenly send an extremly large message out of nowhere. Pages of 0s and 1s with just ./client pid asd.This was the servers reaction:The topmost message was the last from the last image
Does anyone have an idea what is happening?I thought by always reacting to a signal i should not go into any race condition but this behavior is just over my head.
UPDATE:
I used tried using the solution in the related question dimich commented (SIGINFO's si_pid sets itself to 0 after a few calls of the same function)I saved the pid to a static variable in the server and the communication suddenly works without usleep. HOWEVER the client still receives signals with _info->si_pid == 0. And even more interresting: the server sends those 100%. They are ack's the server sends. if i filter them out the client will hang waiting for an ack. I am also on Mac btw.