All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: "Gábor Melis" <mega@retes.hu>
Cc: linux-kernel@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org>
Subject: Re: Signal delivery order
Date: Sun, 15 Mar 2009 10:44:00 +0100	[thread overview]
Message-ID: <20090315094400.GA455@redhat.com> (raw)
In-Reply-To: <200903141750.37238.mega@retes.hu>

On 03/14, Gábor Melis wrote:
>
> The test program triggers sigsegvs from a thread and tests whether the
> the sigsegv handler is invoked when the sigusr1 handler is already
> running.

No, this is not what happens with this test case. SIGSEGV can't be
generated when we run SIGUSR1 handler.

	void sigsegv_handler(int signal, siginfo_t *info, void *context)
	{
	     /* The test signal is blocked only in test_handler. */

The comment is not right. We can't be here (in SIGSEGV handler) if
we are in test_handler.

	     if (is_signal_blocked(test_signal)) {
		 _exit(27);
	     }

If test_signal (SIGUSR1) is blocked, this means it is already delivered,
and the handler will be invoked when we return from sigsegv_handler(),
please see below.

> A normal kill does
> not seem to do this.

Yes. Because the task deques the private signals first (sent by tkill,
or generate by kernel when the test case does "*page_address = 1"),
then it dequeues the shared signals (sent by kill).

But please note that it is still possible to hit is_signal_blocked()
even with test_with_kill(), but the probability is very low.

> I would expect that no asynchronously generated signal (and here I
> include those sent by pthread_kill()) can overtake a sigsegv even if
> its signum is lower.

Signum doesn't matter. Any unblocked signal can preempt the task, whether
it runs inside a signal handler or not. This is correct, you can use
sigaction->sa_mask to specify which signals which should be blocked during
execution of the signal handler.

OK, let's do a simple test:

	int is_blocked(int sig)
	{
		sigset_t set;
		sigprocmask(SIG_BLOCK, NULL, &set);
		return sigismember(&set, sig);
	}

	void sig_1(int sig)
	{
		printf("%d %d\n", sig, is_blocked(2));
	}

	void sig_2(int sig)
	{
		printf("%d %d\n", sig, is_blocked(1));
	}

	int main(void)
	{
		sigset_t set;

		signal(1, sig_1);
		signal(2, sig_2);

		sigemptyset(&set);
		sigaddset(&set, 1);
		sigaddset(&set, 2);
		sigprocmask(SIG_BLOCK, &set, NULL);

		kill(getpid(), 1);
		kill(getpid(), 2);

		sigprocmask(SIG_UNBLOCK, &set, NULL);

		return 0;
	}

output is:

	2 1
	1 0

When sigprocmask(SIG_UNBLOCK) returns, both signals are delivered.
The kernel deques 1 first, then 2. This means that the handler for
"2" will be called first.

But if you change kill(getpid(), 2) to tkill(getpid(), 2)) then the
output should be:

	1 1
	2 0

So, what happens with test_with_pthread_kill() is: the sub-thread
likely deques both signals, SIGSEGV=11 and SIGUSR1=10 and starts
the handler for SIGSEGV.

With test_with_kill(), the child dequeues both signals too, but
runs the handler for SIGUSR1 first, because it was send by kill(),
not tkill().

If you modify your test-case so that test_signal == SIGIO, then
I bet test_with_pthread_kill() won't hit is_signal_blocked() too.
Or you can modify test_with_kill() to use tkill(), in that case
you should see the same behaviour as with test_with_pthread_kill().

Please don't hesitate to ask more questions.

Oleg.


  reply	other threads:[~2009-03-15  9:48 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-03-14 16:50 Signal delivery order Gábor Melis
2009-03-15  9:44 ` Oleg Nesterov [this message]
2009-03-15 14:40   ` Gábor Melis
2009-03-15 17:29     ` Oleg Nesterov
2009-03-15 22:06       ` Gábor Melis
2009-03-16  0:28         ` Oleg Nesterov
2009-03-16  8:34           ` Gábor Melis
2009-03-16 21:13             ` Oleg Nesterov
2009-03-16 22:56               ` Chris Friesen
2009-03-17  4:13                 ` Q: SEGSEGV && uc_mcontext->ip (Was: Signal delivery order) Oleg Nesterov
2009-03-17  4:25                   ` Oleg Nesterov
2009-03-17  8:23                   ` Gábor Melis
2009-03-17  9:25                     ` Oleg Nesterov
2009-03-17 10:20                       ` Gábor Melis
2009-03-17 10:43                         ` Oleg Nesterov
2009-03-17 15:56                     ` Linus Torvalds
2009-03-17 19:20                       ` Q: SEGSEGV && uc_mcontext->ip David Miller
2009-03-18  9:58                       ` Q: SEGSEGV && uc_mcontext->ip (Was: Signal delivery order) Gábor Melis
2009-03-18  7:59                   ` Roland McGrath
2009-03-18  9:02                     ` RT signal queue overflow (Was: Q: SEGSEGV && uc_mcontext->ip (Was: Signal delivery order)) Gábor Melis
2009-03-18 14:52                       ` Linus Torvalds
2009-03-18 15:23                         ` Gábor Melis

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090315094400.GA455@redhat.com \
    --to=oleg@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mega@retes.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.