public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] signals: real-time signals delivery order
@ 2007-07-11  1:12 Anton Salikhmetov
  2007-07-11  7:34 ` Matthieu CASTET
  0 siblings, 1 reply; 3+ messages in thread
From: Anton Salikhmetov @ 2007-07-11  1:12 UTC (permalink / raw)
  To: linux-kernel

From: Anton Salikhmetov <salikhmetov@gmail.com>

According to the POSIX standard, multiple real-time signals
pending to a process should be delivered in a strict order.
Specifically, the lowest-numbered signal should be delivered
first and multiple occurrences of signals with the same number
should be delivered in FIFO order.

Current Linux kernel delivers the highest-numbered signals
pending to a process first, not the lowest-numbered ones. This
contradicts to the requirement explained above. The problem can
be demonstrated by the following test program:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define SIG_RAND (SIGRTMIN + rand() % (SIGRTMAX - SIGRTMIN + 1))
#define NUMSIG 7

struct {
	int sig, num;
} seq[NUMSIG];

void sh(int sig, siginfo_t *info, void *unused)
{
	static int cnt;
	seq[cnt].num = info->si_value.sival_int;
	seq[cnt++].sig = sig;
}

int main(int argc, char *argv[])
{
	int i;
	pid_t p = getpid();
	struct sigaction sa;
	sigset_t ss, ssold;
	union sigval sv;

	sigemptyset(&ss);
	for (i = SIGRTMIN; i <= SIGRTMAX; i++) {
		sa.sa_sigaction = sh;
		sa.sa_flags = SA_SIGINFO;
		sigemptyset(&sa.sa_mask);
		sigaction(i, &sa, NULL);
		sigaddset(&ss, i);
	}

	sigprocmask(SIG_BLOCK, &ss, &ssold);
	switch (fork()) {
		case -1:
			perror("fork()");
			return 1;
		case 0:
			srand(time(NULL));
			for (i = 0; i < NUMSIG; i++) {
				sv.sival_int = i;
				sigqueue(p, SIG_RAND, sv);
			}
			return 0;
		default:
			wait(NULL);
	}
	sigprocmask(SIG_SETMASK, &ssold, NULL);

	for (i = 0; i < NUMSIG; i++)
		printf("SIGRTMIN + %2d, sent with number %d\n",
			seq[i].sig - SIGRTMIN, seq[i].num);
	return 0;
}

Example of the program output for the original kernel:

SIGRTMIN + 23, sent with number 0
SIGRTMIN + 21, sent with number 1
SIGRTMIN + 21, sent with number 6
SIGRTMIN + 16, sent with number 2
SIGRTMIN + 15, sent with number 3
SIGRTMIN + 14, sent with number 4
SIGRTMIN +  5, sent with number 5

Example of the program output for the patched kernel:

SIGRTMIN + 2, sent with number 1
SIGRTMIN + 3, sent with number 0
SIGRTMIN + 17, sent with number 3
SIGRTMIN + 23, sent with number 5
SIGRTMIN + 25, sent with number 2
SIGRTMIN + 29, sent with number 6
SIGRTMIN + 30, sent with number 4

Patch for the Linux 2.6.22.1 kernel:

Signed-off-by: Anton Salikhmetov <salikhmetov@gmail.com>
---
--- linux-2.6.22.1.orig/kernel/signal.c	2007-07-10 22:56:30.000000000
+0400
+++ linux-2.6.22.1/kernel/signal.c	2007-07-11 04:42:17.000000000 +0400
@@ -134,34 +134,11 @@
 
 int next_signal(struct sigpending *pending, sigset_t *mask)
 {
-	unsigned long i, *s, *m, x;
-	int sig = 0;
-	
-	s = pending->signal.sig;
-	m = mask->sig;
-	switch (_NSIG_WORDS) {
-	default:
-		for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)
-			if ((x = *s &~ *m) != 0) {
-				sig = ffz(~x) + i*_NSIG_BPW + 1;
-				break;
-			}
-		break;
-
-	case 2: if ((x = s[0] &~ m[0]) != 0)
-			sig = 1;
-		else if ((x = s[1] &~ m[1]) != 0)
-			sig = _NSIG_BPW + 1;
-		else
-			break;
-		sig += ffz(~x);
-		break;
-
-	case 1: if ((x = *s &~ *m) != 0)
-			sig = ffz(~x) + 1;
-		break;
-	}
-	
+	unsigned long *s = pending->signal.sig, *m = mask->sig, x;
+	int sig = 0, i;
+	for (i = 0; i < _NSIG_WORDS; i++, s++, m++)
+		if ((x = (*s & ~*m)))
+			sig = fls(x) + i * _NSIG_BPW;
 	return sig;
 }


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] signals: real-time signals delivery order
  2007-07-11  1:12 [PATCH] signals: real-time signals delivery order Anton Salikhmetov
@ 2007-07-11  7:34 ` Matthieu CASTET
  2007-07-11  9:10   ` Anton Salikhmetov
  0 siblings, 1 reply; 3+ messages in thread
From: Matthieu CASTET @ 2007-07-11  7:34 UTC (permalink / raw)
  To: linux-kernel

Anton Salikhmetov <salikhmetov <at> gmail.com> writes:

> 
> From: Anton Salikhmetov <salikhmetov <at> gmail.com>
> 
> According to the POSIX standard, multiple real-time signals
> pending to a process should be delivered in a strict order.
> Specifically, the lowest-numbered signal should be delivered
> first and multiple occurrences of signals with the same number
> should be delivered in FIFO order.
> 
> Current Linux kernel delivers the highest-numbered signals
> pending to a process first, not the lowest-numbered ones. This
> contradicts to the requirement explained above. The problem can
> be demonstrated by the following test program:
I believe you should check that you mask or signal in your signal handler.
If you don't the high-prio handler will be prempted by low-prio, and they will
be executed in the reverse order.


Matthieu 


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] signals: real-time signals delivery order
  2007-07-11  7:34 ` Matthieu CASTET
@ 2007-07-11  9:10   ` Anton Salikhmetov
  0 siblings, 0 replies; 3+ messages in thread
From: Anton Salikhmetov @ 2007-07-11  9:10 UTC (permalink / raw)
  To: Matthieu CASTET; +Cc: linux-kernel

В Срд, 11/07/2007 в 07:34 +0000, Matthieu CASTET пишет:
> Anton Salikhmetov <salikhmetov <at> gmail.com> writes:
> 
> > 
> > From: Anton Salikhmetov <salikhmetov <at> gmail.com>
> > 
> > According to the POSIX standard, multiple real-time signals
> > pending to a process should be delivered in a strict order.
> > Specifically, the lowest-numbered signal should be delivered
> > first and multiple occurrences of signals with the same number
> > should be delivered in FIFO order.
> > 
> > Current Linux kernel delivers the highest-numbered signals
> > pending to a process first, not the lowest-numbered ones. This
> > contradicts to the requirement explained above. The problem can
> > be demonstrated by the following test program:
> I believe you should check that you mask or signal in your signal handler.
> If you don't the high-prio handler will be prempted by low-prio, and they will
> be executed in the reverse order.
> 

Thanks, I have modified the test program blocking the signals for the
duration of the signal handler as follows:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define SIG_RAND (SIGRTMIN + rand() % (SIGRTMAX - SIGRTMIN + 1))
#define NUMSIG 7

struct {
	int sig, num;
} seq[NUMSIG];

void sh(int sig, siginfo_t *info, void *unused)
{
	static int cnt;
	seq[cnt].num = info->si_value.sival_int;
	seq[cnt++].sig = sig;
}

int main(int argc, char *argv[])
{
	int i;
	pid_t p = getpid();
	struct sigaction sa;
	sigset_t ss, ssold;
	union sigval sv;

	sigemptyset(&ss);
	for (i = SIGRTMIN; i <= SIGRTMAX; i++) {
		sa.sa_sigaction = sh;
		sa.sa_flags = SA_SIGINFO;
		sigfillset(&sa.sa_mask);
		sigaction(i, &sa, NULL);
		sigaddset(&ss, i);
	}

	sigprocmask(SIG_BLOCK, &ss, &ssold);
	switch (fork()) {
		case -1:
			perror("fork()");
			return 1;
		case 0:
			srand(time(NULL));
			for (i = 0; i < NUMSIG; i++) {
				sv.sival_int = i;
				sigqueue(p, SIG_RAND, sv);
			}
			return 0;
		default:
			wait(NULL);
	}
	sigprocmask(SIG_SETMASK, &ssold, NULL);

	for (i = 0; i < NUMSIG; i++)
		printf("SIGRTMIN + %2d, sent with number %d\n",
			seq[i].sig - SIGRTMIN, seq[i].num);
	return 0;
}

This modified program works correctly with the original kernel:

SIGRTMIN +  2, sent with number 5
SIGRTMIN +  3, sent with number 2
SIGRTMIN + 10, sent with number 6
SIGRTMIN + 16, sent with number 3
SIGRTMIN + 17, sent with number 4
SIGRTMIN + 18, sent with number 0
SIGRTMIN + 29, sent with number 1

I would like to explain why I got an impression the next_signal()
funtion did not work correctly. When I ran the old test program using a
vendor-specific heavily patched kernel the signals order was as the
POSIX standard specified. Another kernel, which was closer to the
vanilla kernel, did not show the expected behavior. Instead, the signals
were handled in the reversed order.

Sorry for making noise in the mailing list.

Anton

> 
> Matthieu 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-07-11  9:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-11  1:12 [PATCH] signals: real-time signals delivery order Anton Salikhmetov
2007-07-11  7:34 ` Matthieu CASTET
2007-07-11  9:10   ` Anton Salikhmetov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox