Sourceware Bugzilla – Attachment 2959 Details for
Bug 6910
getpid() wrong in child's signal handler after clone()
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Test program
clone_getpid_sighandler_bug.c (text/plain), 3.36 KB, created by
Michael Kerrisk
on 2008-09-22 11:47:13 UTC
(
hide
)
Description:
Test program
Filename:
MIME Type:
Creator:
Michael Kerrisk
Created:
2008-09-22 11:47:13 UTC
Size:
3.36 KB
patch
obsolete
>/*#* clone_getpid_sighandler_bug.c > > As at glibc 2.8, glibc caching of PIDs for getpid() means that > if a signal is delivered to the child soon after a clone() (i.e., > before the child has a chance to update the cache), then > getpid() in the signal handler inside the child returns the wrong > value. > > To test this, this program creates a child process that > continuously sends a SIGQUIT signal to the process group. > Meanwhile the parent loops creating children that sleep > for a moment, and then terminate. In that time, the SIGQUIT > handler will be invoked in the child. If the getpid() cache > has not yet been updated, then it will (occasionally) happen > that the values returned by glibc's getpid() and a raw > syscall(SYS_getpid) will not match. When that occurs, the > child prints a message noting the mismatch. > > If this program is invoked with any command-line argument, then > it uses fork() instead of clone(). This can be used to show that > the problem does not occur for fork(). >*/ >/*#** > Change history > > 22 Sep 08 Initial creation >*/ >#define _GNU_SOURCE >#include <signal.h> >#include <sys/syscall.h> >#include <sys/wait.h> >#include <sched.h> >#include <stdio.h> >#include <stdlib.h> >#include <unistd.h> > >#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ > } while (0) > > >static volatile int loop; >static volatile int gotSig; > > >static int /* Startup function for cloned child */ >childFunc(void *arg) >{ > usleep(1000); /* long ebough to ge a signal */ > return 0; /* Child terminates now */ >} /* childFunc */ > > >static void >handler(int sig) >{ > pid_t pid; > > pid = getpid(); > > if (getpid() != syscall(SYS_getpid)) { > printf("getpid() mismatch (loop=%d): getpid()=%ld; " > "syscall(SYS_getpid)=%ld\n", > loop, > (long) getpid(), (long) syscall(SYS_getpid)); > } > gotSig = 1; >} > > >int >main(int argc, char *argv[]) >{ > const int STACK_SIZE = 65536; /* Stack size for cloned child */ > char *stack; /* Start of stack buffer */ > char *stackTop; /* End of stack buffer */ > int flags; > struct sigaction sa; > int status; > > sa.sa_flags = SA_RESTART; > sa.sa_handler = handler; > sigemptyset(&sa.sa_mask); > if (sigaction(SIGQUIT, &sa, NULL) == -1) > errExit("sigaction"); > > printf("Before clone getpid() = %ld\n", (long) getpid()); > > flags = 0; > > if (fork() == 0) { > if (fork() != 0) > exit(EXIT_SUCCESS); > printf("sigsender PID = %ld\n", (long) getpid()); > for (;;) > killpg(0, SIGQUIT); > } > wait(NULL); > > /* Allocate stack for child */ > > stack = malloc(STACK_SIZE); > if (stack == NULL) > errExit("malloc"); > stackTop = stack + STACK_SIZE; /* Assume stack grows downwards */ > > for (loop = 0; ; loop++) { > if (argc == 1) { > if (clone(childFunc, stackTop, flags | SIGCHLD, NULL) == -1) > errExit("clone"); > } else { > if (fork() == 0) { > childFunc(NULL); > exit(EXIT_SUCCESS); > } > } > > if (waitpid(-1, &status, 0) == -1) > errExit("waitpid"); > if (loop % 100000 == 0 && loop > 0) > printf("loop %d\n", loop); > } > > exit(EXIT_SUCCESS); >} /* main */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 6910
: 2959