Created attachment 102331 [details] test code, compile it using -std=c99 option Assume parent send 3 signals from SIGRTMAX (64) to SIGRTMAX - 2 (62), each signal sends 3 times, the child would recv the signal as order SIGRTMAX - 2 to SIGRTMAX, since the lowest-numbered should delivered first, and each same number signal deliver as FIFO order, but the result is: -----parent send----- sent 64, val = 1 sent 64, val = 2 sent 64, val = 3 sent 63, val = 1 sent 63, val = 2 sent 63, val = 3 sent 62, val = 1 sent 62, val = 2 sent 62, val = 3 -----child recv----- recv 64, val = 1 recv 64, val = 2 recv 64, val = 3 recv 63, val = 1 recv 63, val = 2 recv 63, val = 3 recv 62, val = 1 recv 62, val = 2 recv 62, val = 3 we see that the same number signal deliver in right sequence (FIFO), but different signal DO NOT delivered in lowest number first, in this case, it should be the signal 62 first, and 64 last.
(In reply to comment #0) > > Assume parent send 3 signals from SIGRTMAX (64) to SIGRTMAX - 2 (62), each > signal sends 3 times, the child would recv the signal as order SIGRTMAX - 2 > to > SIGRTMAX, since the lowest-numbered should delivered first, ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Well, this is not true and this was never guaranteed. For example, say, SIGSEGV will be delivered before SIGHUP. (And in fact you meant "dequeued", not delivered ;) But in this particular case this is true. The child dequeues 62 first, then 63, etc. But note that if the task dequeues SIG_A before SIG_B, then the handler for SIG_B will run first! This is correct. Because the task dequeues both signals and setups the frames before it returns to user-space, so the last handler runs first. > recv 64, val = 1 > recv 64, val = 2 > recv 64, val = 3 > recv 63, val = 1 > recv 63, val = 2 > recv 63, val = 3 See above. everything is correct. > we see that the same number signal deliver in right sequence (FIFO), Given the above this probably needs another explanation. This is because the dequeued signal becomes blocked until the signal handler returns. If you change your test-case to add SA_NODEFER to sa_flags the child should print recv 64 val = 3 64 2 64 1 63 2 ... Not a bug.
(In reply to comment #1) > > Not a bug. Just in case. if you want FIFO you can initialize sa_mask to exclude the signals you can "race" with. #include <unistd.h> #include <signal.h> #include <stdio.h> #define SIG_A 62 #define SIG_Z 64 void sig_func(int signum, siginfo_t *info, void *ucp) { printf("recv %d, val = %d\n", signum, info->si_int); } int main(void) { /* Block the signal. */ sigset_t set; struct sigaction sa; union sigval val; int i, j; sigfillset(&set); sigprocmask(SIG_BLOCK, &set, NULL); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO | SA_RESTART; sa.sa_sigaction = sig_func; sigfillset(&sa.sa_mask); /* <--------------------------------- */ for (i = SIG_A; i <= SIG_Z; i++) sigaction(i, &sa, NULL); printf("\nINIT DONE\n"); for (i = SIG_A; i <= SIG_Z; i++) { for (j = 1; j <= 3; j++) { val.sival_int = j; sigqueue(getpid(), i, val); printf("sent %d, val = %d\n", i, j); } } printf("\nSIGNALS SENT\n"); sigprocmask(SIG_UNBLOCK, &set, NULL); return 0; } This code simply does sigfillset(sa_mask), but you only need to block 62-64.
Closing as invalid per Oleg's feedback.
(In reply to comment #1) > Well, this is not true and this was never guaranteed. > For example, say, SIGSEGV will be delivered before SIGHUP. Yes, for normal signal(SIGSEGV SIGHUP etc), it is not true. but for real-time signal, the signal(7) says: Real-time signals are delivered in a guaranteed order. Multiple real-time signals of the same type are delivered in the order they were sent. If different real-time signals are sent to a process, they are delivered starting with the lowest-numbered signal. > (And in fact you meant "dequeued", not delivered ;) > > But in this particular case this is true. The child dequeues > 62 first, then 63, etc. > > But note that if the task dequeues SIG_A before SIG_B, then > the handler for SIG_B will run first! This is correct. Because > the task dequeues both signals and setups the frames before > it returns to user-space, so the last handler runs first. > > > recv 64, val = 1 > > recv 64, val = 2 > > recv 64, val = 3 > > recv 63, val = 1 > > recv 63, val = 2 > > recv 63, val = 3 > > See above. everything is correct. > > > we see that the same number signal deliver in right sequence (FIFO), > > Given the above this probably needs another explanation. This is > because the dequeued signal becomes blocked until the signal handler > returns. If you change your test-case to add SA_NODEFER to sa_flags > the child should print > > recv 64 val = 3 > 64 2 > 64 1 > 63 2 > ... > > Not a bug.
(In reply to comment #1) > But in this particular case this is true. The child dequeues > 62 first, then 63, etc. > > But note that if the task dequeues SIG_A before SIG_B, then > the handler for SIG_B will run first! This is correct. Because > the task dequeues both signals and setups the frames before > it returns to user-space, so the last handler runs first. > > > recv 64, val = 1 > > recv 64, val = 2 > > recv 64, val = 3 > > recv 63, val = 1 > > recv 63, val = 2 > > recv 63, val = 3 > > See above. everything is correct. Yes, this I got it. but I do not understand why man page say "If different real-time signals are sent to a process, they are _delivered_ starting with the lowest-numbered signal."
(In reply to comment #5) > > but I do not understand why man page say "If different real-time signals are > sent to a process, they are _delivered_ starting with the > lowest-numbered signal." I have no idea. Except, as I already said, they are actually delivered starting with the lowest-numbered signal, just this doesn't mean the handers will run in the same order. Imho the man page should be fixed. Look. Whatever the kernel does, you can't expect FIFO (in a sense you described). Suppose that you send SIG_63 then SIG_64 to the task T. What if the signal handler for SIG_63 has already started by the time you send SIG_64? Depending on the timing, you can observe that the handler for SIG_64 runs before or after.