S
subnet
I'm trying to write a very simple program that uses a signal-based
synchronization between two processes. Here's it:
-----------------------------------------------
/* The world's simplest syncronization example */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig);
void wait_signal();
int main() {
sigset_t curr_mask;
struct sigaction act;
pid_t pid;
act.sa_handler = handler;
sigaction(SIGUSR1, &act, NULL);
sigprocmask(0, NULL, &curr_mask);
sigaddset(&curr_mask, SIGUSR1);
sigprocmask(SIG_SETMASK, &curr_mask, NULL);
pid = fork();
/* Strict alternation */
if (pid > 0) {
while(1) {
printf("Parent\n");
/* Tell the child we're done */
kill(pid, SIGUSR1);
wait_signal();
}
}
else {
pid_t parent_pid = getppid();
while(1) {
wait_signal();
printf("Child\n");
/* Tell the parent we're done */
kill(parent_pid, SIGUSR1);
}
}
}
void handler(int sig) {
/* do nothing, just used for sync */
}
void wait_signal() {
sigset_t mask;
sigemptyset(&mask);
sigsuspend(&mask);
}
-----------------------------------------------
With a 2.6 linux kernel, this hangs miserably with this output:
Parent
Child
Parent
Doing an strace yelds the following result:
-------------------
execve("./myprog", ["./myprog"], [/* 56 vars */]) = 0
uname({sys="Linux", node="scooter", ...}) = 0
brk(0) = 0x501000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556b000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62108, ...}) = 0
mmap(NULL, 62108, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a9556c000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\315\1\0"...,
640) = 640
lseek(3, 624, SEEK_SET) = 624
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0"...,
32) = 32
fstat(3, {st_mode=S_IFREG|0755, st_size=1232856, ...}) = 0
mmap(NULL, 2215816, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x2a9566b000
mprotect(0, 1085320, PROT_NONE) = -1 ENOMEM (Cannot allocate
memory)
mmap(0x2a9586b000, 102400, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 3, 0x100000) = 0x2a9586b000
mmap(0x2a95884000, 16264, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2a95884000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a95888000
arch_prctl(0x1002, 0x2a95888640) = 0
munmap(0x2a9556c000, 62108) = 0
open("/dev/urandom", O_RDONLY) = 3
read(3, "\304fd\200\34\2727f\333\316\335\370\334\251\332Pi\235-"...,
64) = 64
close(3) = 0
rt_sigaction(SIGUSR1, {0x400819, [HUP],
SA_RESTART|SA_ONESHOT|SA_NOCLDSTOP|0x555fa10}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [USR1], NULL, 8) = 0
clone(child_stack=0,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x2a958886d0) = 16791
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556c000
write(1, "Parent\n", 7Parent
) = 7
kill(16791, SIGUSR1) = 0
rt_sigsuspend([]Child
<unfinished ...>
--- SIGUSR1 (User defined signal 1) @ 0 (0) ---
<... rt_sigsuspend resumed> ) = -1 EINTR (Interrupted system
call)
rt_sigreturn(0xa) = -1 EINTR (Interrupted system
call)
write(1, "Parent\n", 7Parent
) = 7
kill(16791, SIGUSR1) = 0
rt_sigsuspend([] <unfinished ...>
--- SIGCHLD (Child exited) @ 0 (0) ---
----------------------------------------
And that's why it hangs, of course. The call to rt_sigaction shows
that it's called with the flag (among the others) SA_ONESHOT.
The funny part comes now: if I modify line 11 from
sigset_t curr_mask;
to, say
sigset_t curr_mask, mask1, mask2; /* add two unused variables */
it runs just fine!!
Here's the strace output (only the beginning, of course)
-------------------------------------------------
execve("./myprog", ["./myprog"], [/* 56 vars */]) = 0
uname({sys="Linux", node="scooter", ...}) = 0
brk(0) = 0x501000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556b000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62108, ...}) = 0
mmap(NULL, 62108, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a9556c000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\315\1\0"...,
640) = 640
lseek(3, 624, SEEK_SET) = 624
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0"...,
32) = 32
fstat(3, {st_mode=S_IFREG|0755, st_size=1232856, ...}) = 0
mmap(NULL, 2215816, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x2a9566b000
mprotect(0, 1085320, PROT_NONE) = -1 ENOMEM (Cannot allocate
memory)
mmap(0x2a9586b000, 102400, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 3, 0x100000) = 0x2a9586b000
mmap(0x2a95884000, 16264, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2a95884000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a95888000
arch_prctl(0x1002, 0x2a95888640) = 0
munmap(0x2a9556c000, 62108) = 0
open("/dev/urandom", O_RDONLY) = 3
read(3, "\235!\fl\347\370Y\20}$\4\232N97\263W\201\317\273\4\230"...,
64) = 64
close(3) = 0
rt_sigaction(SIGUSR1, {0x400819, [ILL TRAP ABRT FPE USR1 SEGV USR2
PIPE ALRM STKFLT CONT STOP TTIN URG XFSZ PROF IO RTMIN RT_2 RT_4
RT_6], SA_NOCLDSTOP|0x4000000}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [USR1], NULL, 8) = 0
clone(child_stack=0,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x2a958886d0) = 16892
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556c000
--------------------------------------------------------
This shows that rt_sigaction is called with different arguments this
time (without SA_ONESHOT)!
What's going on here? This is driving me mad. The compiler is
gcc-3.3.3.
Thanks for any help.
synchronization between two processes. Here's it:
-----------------------------------------------
/* The world's simplest syncronization example */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void handler(int sig);
void wait_signal();
int main() {
sigset_t curr_mask;
struct sigaction act;
pid_t pid;
act.sa_handler = handler;
sigaction(SIGUSR1, &act, NULL);
sigprocmask(0, NULL, &curr_mask);
sigaddset(&curr_mask, SIGUSR1);
sigprocmask(SIG_SETMASK, &curr_mask, NULL);
pid = fork();
/* Strict alternation */
if (pid > 0) {
while(1) {
printf("Parent\n");
/* Tell the child we're done */
kill(pid, SIGUSR1);
wait_signal();
}
}
else {
pid_t parent_pid = getppid();
while(1) {
wait_signal();
printf("Child\n");
/* Tell the parent we're done */
kill(parent_pid, SIGUSR1);
}
}
}
void handler(int sig) {
/* do nothing, just used for sync */
}
void wait_signal() {
sigset_t mask;
sigemptyset(&mask);
sigsuspend(&mask);
}
-----------------------------------------------
With a 2.6 linux kernel, this hangs miserably with this output:
Parent
Child
Parent
Doing an strace yelds the following result:
-------------------
execve("./myprog", ["./myprog"], [/* 56 vars */]) = 0
uname({sys="Linux", node="scooter", ...}) = 0
brk(0) = 0x501000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556b000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62108, ...}) = 0
mmap(NULL, 62108, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a9556c000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\315\1\0"...,
640) = 640
lseek(3, 624, SEEK_SET) = 624
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0"...,
32) = 32
fstat(3, {st_mode=S_IFREG|0755, st_size=1232856, ...}) = 0
mmap(NULL, 2215816, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x2a9566b000
mprotect(0, 1085320, PROT_NONE) = -1 ENOMEM (Cannot allocate
memory)
mmap(0x2a9586b000, 102400, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 3, 0x100000) = 0x2a9586b000
mmap(0x2a95884000, 16264, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2a95884000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a95888000
arch_prctl(0x1002, 0x2a95888640) = 0
munmap(0x2a9556c000, 62108) = 0
open("/dev/urandom", O_RDONLY) = 3
read(3, "\304fd\200\34\2727f\333\316\335\370\334\251\332Pi\235-"...,
64) = 64
close(3) = 0
rt_sigaction(SIGUSR1, {0x400819, [HUP],
SA_RESTART|SA_ONESHOT|SA_NOCLDSTOP|0x555fa10}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [USR1], NULL, 8) = 0
clone(child_stack=0,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x2a958886d0) = 16791
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556c000
write(1, "Parent\n", 7Parent
) = 7
kill(16791, SIGUSR1) = 0
rt_sigsuspend([]Child
<unfinished ...>
--- SIGUSR1 (User defined signal 1) @ 0 (0) ---
<... rt_sigsuspend resumed> ) = -1 EINTR (Interrupted system
call)
rt_sigreturn(0xa) = -1 EINTR (Interrupted system
call)
write(1, "Parent\n", 7Parent
) = 7
kill(16791, SIGUSR1) = 0
rt_sigsuspend([] <unfinished ...>
--- SIGCHLD (Child exited) @ 0 (0) ---
----------------------------------------
And that's why it hangs, of course. The call to rt_sigaction shows
that it's called with the flag (among the others) SA_ONESHOT.
The funny part comes now: if I modify line 11 from
sigset_t curr_mask;
to, say
sigset_t curr_mask, mask1, mask2; /* add two unused variables */
it runs just fine!!
Here's the strace output (only the beginning, of course)
-------------------------------------------------
execve("./myprog", ["./myprog"], [/* 56 vars */]) = 0
uname({sys="Linux", node="scooter", ...}) = 0
brk(0) = 0x501000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556b000
open("/etc/ld.so.preload", O_RDONLY) = -1 ENOENT (No such file or
directory)
open("/etc/ld.so.cache", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=62108, ...}) = 0
mmap(NULL, 62108, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2a9556c000
close(3) = 0
open("/lib/libc.so.6", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0`\315\1\0"...,
640) = 640
lseek(3, 624, SEEK_SET) = 624
read(3, "\4\0\0\0\20\0\0\0\1\0\0\0GNU\0\0\0\0\0\2\0\0\0\6\0\0\0"...,
32) = 32
fstat(3, {st_mode=S_IFREG|0755, st_size=1232856, ...}) = 0
mmap(NULL, 2215816, PROT_READ|PROT_EXEC, MAP_PRIVATE, 3, 0) =
0x2a9566b000
mprotect(0, 1085320, PROT_NONE) = -1 ENOMEM (Cannot allocate
memory)
mmap(0x2a9586b000, 102400, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED, 3, 0x100000) = 0x2a9586b000
mmap(0x2a95884000, 16264, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2a95884000
close(3) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a95888000
arch_prctl(0x1002, 0x2a95888640) = 0
munmap(0x2a9556c000, 62108) = 0
open("/dev/urandom", O_RDONLY) = 3
read(3, "\235!\fl\347\370Y\20}$\4\232N97\263W\201\317\273\4\230"...,
64) = 64
close(3) = 0
rt_sigaction(SIGUSR1, {0x400819, [ILL TRAP ABRT FPE USR1 SEGV USR2
PIPE ALRM STKFLT CONT STOP TTIN URG XFSZ PROF IO RTMIN RT_2 RT_4
RT_6], SA_NOCLDSTOP|0x4000000}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [USR1], NULL, 8) = 0
clone(child_stack=0,
flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD,
child_tidptr=0x2a958886d0) = 16892
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 2), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1,
0) = 0x2a9556c000
--------------------------------------------------------
This shows that rt_sigaction is called with different arguments this
time (without SA_ONESHOT)!
What's going on here? This is driving me mad. The compiler is
gcc-3.3.3.
Thanks for any help.