From: "Michael Kerrisk" <mtk-lkml@gmx.net>
To: roland@redhat.com
Cc: linux-kernel@vger.kernel.org, michael.kerrisk@gmx.net
Subject: waitid() fails with EINVAL for SA_RESTART signals
Date: Wed, 18 May 2005 10:20:47 +0200 (MEST) [thread overview]
Message-ID: <24601.1116404447@www71.gmx.net> (raw)
Hello Roland,
I'm seeing a strange behaviour with waitid() in 2.6.12-rc3
(I'm fairly sure the behaviour also appears in other 2.6.x).
If we establish a handler for a signal with SA_RESTART, and that
signal interrupts a blocked waitid(), then waitid() fails with
the error EINVAL. I would expect the call to be restarted
(like wait(), waitpid(), etc.) or if you are choosing to design
waitid() to ignore SA_RESTART, then fail with EINTR.
I haven't been able to spot the source of the EINVAL in kernel
or glibc sources.
The program below can be used to demonstrate the problem.
Cheers,
Michael
/* waitid_intr.c
Michael Kerrisk, May 2005
Demonstration of a problem with waitid() on Linux (Linux 2.6.12-rc3).
If S_A_RESTART was specified for a signal handler, and that signal
is delivered during a blocked waitid(), then the waitid() fails
with EINVAL, when it should either be restarted or (if the intent
is to ignore SA_RESTART in the waitid() implementation) fail
with EINTR. This program demonstrates the problem.
The program creates two children. The first is a child that sleeps
for argv[2] seconds and is then reaped by waitid() in the parent.
The second child sends a signal (SIG) to the parent after argv[3]
seconds.
argv[1] specifies options for the waitid() call (see the code
below).
If the optional argv[4] is present (as any string), then the
handler for the signal sent by the second child is established
with SA_RESTART.
To demonstrate the waitid() problem, use the following command:
./waitid_intr esc 10 2 restart
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <syscall.h>
#include <unistd.h>
#include <errno.h>
#define errExit(msg) { perror(msg); exit(EXIT_FAILURE); }
#define fatalErr(msg) { fprintf(stderr, "%s\n", msg); \
exit(EXIT_FAILURE); }
static void
handler(int sig)
{
int savedErrno;
savedErrno = errno;
printf("Caught signal\n");
errno = savedErrno;
} /* handler */
#define SIG SIGUSR1
int
main(int argc, char *argv[])
{
siginfo_t info;
int options, s;
char *p;
pid_t pid;
struct rusage ru;
struct sigaction sa;
setbuf(stdout, NULL);
printf("Parent's PID is %ld\n", (long) getpid());
if (argc < 4) {
fprintf(stderr, "%s {escHW} child-secs sig-secs [sa_restart]\n",
argv[0]);
exit(EXIT_FAILURE);
}
options = 0;
for (p = argv[1]; *p != '\0'; p++) {
if (*p == 'e') options |= WEXITED;
else if (*p == 's') options |= WSTOPPED;
else if (*p == 'c') options |= WCONTINUED;
else if (*p == 'H') options |= WNOHANG;
else if (*p == 'W') options |= WNOWAIT;
else fatalErr("Bad option letter");
}
/* Create first child to waitid() for */
pid = fork();
if (pid == -1) errExit("fork");
if (pid == 0) {
printf("child (PID = %ld) started\n", (long) getpid());
sleep(atoi(argv[2]));
printf("child (PID = %ld) finished\n", (long) getpid());
exit(EXIT_SUCCESS);
}
/* Parent falls through */
/* Set up handler for signal sent by child 2 */
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = (argc > 4) ? SA_RESTART : 0;
if (sigaction(SIG, &sa, NULL) == -1) errExit("sigaction");
/* Create a second child that will send parent a signal */
switch (fork()) {
case -1:
errExit("fork-2");
case 0:
sleep(atoi(argv[3]));
printf("Sending signal to parent\n");
if (kill(getppid(), SIG) == -1) errExit("kill");
exit(EXIT_SUCCESS);
default:
break;
}
/* Parent now waits for the first child */
memset(&info, 0, sizeof(siginfo_t));
s = waitid(P_PID, pid, &info, options);
//s = syscall(SYS_waitid, P_ALL, 0, &info, options, &ru);
//s = syscall(SYS_waitpid, -1, NULL, 0);
if (s == -1) errExit("waitid");
printf("waitid() returned %d\n", s);
printf(" ");
printf("si_pid=%ld; ", (long) info.si_pid);
printf("si_uid=%ld; ", (long) info.si_uid);
printf("si_signo=%ld; ", (long) info.si_signo);
printf("\n");
printf(" ");
printf("si_status=%ld; ", (long) info.si_status);
printf("si_code=%ld ", (long) info.si_code);
printf("(%s); ",
(info.si_code == CLD_EXITED) ? "CLD_EXITED" :
(info.si_code == CLD_KILLED) ? "CLD_KILLED" :
(info.si_code == CLD_DUMPED) ? "CLD_DUMPED" :
(info.si_code == CLD_TRAPPED) ? "CLD_TRAPPED" :
(info.si_code == CLD_STOPPED) ? "CLD_STOPPED" :
(info.si_code == CLD_CONTINUED) ? "CLD_CONTINUED" :
"????");
printf("\n");
} /* main */
--
Weitersagen: GMX DSL-Flatrates mit Tempo-Garantie!
Ab 4,99 Euro/Monat: http://www.gmx.net/de/go/dsl
next reply other threads:[~2005-05-18 8:21 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-18 8:20 Michael Kerrisk [this message]
2005-05-26 21:17 ` waitid() fails with EINVAL for SA_RESTART signals Roland McGrath
2005-05-26 22:21 ` [PATCH] i386: fix prevent_tail_call Roland McGrath
2005-05-26 22:22 ` waitid() fails with EINVAL for SA_RESTART signals Roland McGrath
2005-05-26 22:37 ` David S. Miller
2005-05-26 23:19 ` Linus Torvalds
2005-05-26 23:22 ` Roland McGrath
2005-05-27 0:03 ` Parag Warudkar
2005-05-27 0:11 ` Roland McGrath
2005-05-27 0:37 ` Parag Warudkar
2005-05-27 1:05 ` Parag Warudkar
2005-05-27 2:01 ` Parag Warudkar
2005-05-30 16:55 ` Michael Kerrisk
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=24601.1116404447@www71.gmx.net \
--to=mtk-lkml@gmx.net \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.kerrisk@gmx.net \
--cc=roland@redhat.com \
/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.