Browse Source
libposix: deep refactor; add sys/posixly command
libposix: deep refactor; add sys/posixly command
With these changes, libposix (and newlib) can run MirBSD Korn Shell.master
56 changed files with 4937 additions and 606 deletions
-
2cfg/mksh/profile
-
5qa/check
-
10qa/kern/awake.c
-
2qa/lib/c/qlockt2.c
-
4qa/lib/c/rlockt1.c
-
2qa/lib/c/rlockt2.c
-
2qa/lib/c/rsleept2.c
-
2qa/lib/c/wlockt2.c
-
7qa/lib/newlib/001-hello.c
-
27qa/lib/newlib/002-atexit.c
-
44qa/lib/newlib/041-env.c
-
32qa/lib/newlib/041-env.runner
-
71qa/lib/newlib/050-setsid.c
-
2qa/lib/newlib/050-setsid.runner
-
48qa/lib/newlib/120-fcntl.c
-
82qa/lib/newlib/121-fcntl.c
-
7qa/lib/newlib/200-signals.c
-
7qa/lib/newlib/201-signals.c
-
6qa/lib/newlib/202-signals.c
-
8qa/lib/newlib/203-signals.c
-
6qa/lib/newlib/204-signals.c
-
51qa/lib/newlib/206-signals.c
-
74qa/lib/newlib/207-sigsuspend.c
-
69qa/lib/newlib/208-sigpending.c
-
54qa/lib/newlib/209-sigwaitinfo.c
-
58qa/lib/newlib/210-sigtimedwait.c
-
61qa/lib/newlib/211-sigtimedwait.c
-
54qa/lib/newlib/212-sigwait.c
-
88qa/lib/newlib/213-sigqueue.c
-
132qa/lib/newlib/214-sigsetjmp.c
-
38qa/lib/newlib/215-sigprocmask.c
-
36qa/lib/newlib/build.json
-
20qa/lib/newlib/libposix_customization.c
-
20qa/lib/newlib/libposix_sigchld.c
-
271sys/include/posix.h
-
6sys/src/cmd/sys/build.json
-
4sys/src/lib/libs.json
-
22sys/src/lib/posix/build.json
-
96sys/src/lib/posix/environment.c
-
35sys/src/lib/posix/errors.c
-
159sys/src/lib/posix/fcntl.c
-
71sys/src/lib/posix/files.c
-
217sys/src/lib/posix/ids.c
-
84sys/src/lib/posix/initlib.c
-
86sys/src/lib/posix/internal.h
-
50sys/src/lib/posix/kill.c
-
9sys/src/lib/posix/others.c
-
1941sys/src/lib/posix/posixly.c
-
124sys/src/lib/posix/processes.c
-
223sys/src/lib/posix/sigchlds.c
-
558sys/src/lib/posix/signals.c
-
49sys/src/lib/posix/sigqueue.c
-
292sys/src/lib/posix/sigsets.c
-
46sys/src/lib/posix/sigsuspend.c
-
62sys/src/lib/posix/termios.c
-
7sys/src/lib/posix/timers.c
@ -0,0 +1,2 @@ |
|||
export PWD=`cat /dev/wdir` |
|||
export HOSTNAME=$SYSNAME |
@ -0,0 +1,7 @@ |
|||
#include <stdio.h> |
|||
int main() |
|||
{ |
|||
fprintf(stdout, "hello, stdout\n"); |
|||
fprintf(stderr, "hello, stderr\n"); |
|||
return 0; |
|||
} |
@ -0,0 +1,27 @@ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
|
|||
void |
|||
bye(void) |
|||
{ |
|||
printf("That was all, folks\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
int |
|||
main(void) |
|||
{ |
|||
// long a; |
|||
int i; |
|||
|
|||
// a = sysconf(_SC_ATEXIT_MAX); |
|||
// printf("ATEXIT_MAX = %ld\n", a); |
|||
|
|||
i = atexit(bye); |
|||
if (i != 0) { |
|||
fprintf(stderr, "cannot set exit function\n"); |
|||
return 1; |
|||
} |
|||
return 2; |
|||
} |
@ -0,0 +1,44 @@ |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <sys/types.h> |
|||
#include <sys/wait.h> |
|||
|
|||
int |
|||
main () |
|||
{ |
|||
int child, status; |
|||
printf("Parent $PATH = %s\n", getenv("PATH")); |
|||
printf("Parent $HOME = %s\n", getenv("HOME")); |
|||
printf("Parent $USER = %s\n", getenv("USER")); |
|||
printf("Parent $IFS = %s\n", getenv("IFS")); |
|||
printf("Parent $ROOT = %s\n", getenv("ROOT")); |
|||
printf("Parent $TEST = %s\n", getenv("TEST")); |
|||
putenv("TEST=value"); |
|||
printf("Parent putenv(TEST=value); now $TEST = %s\n", getenv("TEST")); |
|||
fflush(stdout); |
|||
|
|||
switch(child = fork()){ |
|||
case 0: |
|||
printf("Child $PATH = %s\n", getenv("PATH")); |
|||
printf("Child $HOME = %s\n", getenv("HOME")); |
|||
printf("Child $USER = %s\n", getenv("USER")); |
|||
printf("Child $IFS = %s\n", getenv("IFS")); |
|||
printf("Child $ROOT = %s\n", getenv("ROOT")); |
|||
printf("Child $TEST = %s\n", getenv("TEST")); |
|||
exit(0); |
|||
case -1: |
|||
printf("FAIL: fork\n"); |
|||
return 1; |
|||
default: |
|||
wait(&status); |
|||
break; |
|||
} |
|||
|
|||
unsetenv("TEST"); |
|||
printf("Parent unsetenv(TEST); now $TEST = %s\n", getenv("TEST")); |
|||
|
|||
if(status) |
|||
printf("FAIL: child returned %d\n", status); |
|||
exit(status); |
|||
} |
@ -0,0 +1,32 @@ |
|||
#!/cmd/rc |
|||
runner=$0 |
|||
test = `{echo $runner|sed 's/.runner//'} |
|||
test_output = /tmp/output-`{basename $test} |
|||
|
|||
if ( test -e $test_output) rm $test_output |
|||
|
|||
$test > $test_output |
|||
|
|||
expected_lines = ('Parent \$PATH = /cmd:.' \ |
|||
'Parent \$HOME = '^$HOME \ |
|||
'Parent \$USER = '^$USER \ |
|||
'Parent \$ROOT = \(null\)' \ |
|||
'Parent \$TEST = \(null\)' \ |
|||
'Parent putenv\(TEST=value\); now \$TEST = value' \ |
|||
'Child \$PATH = /cmd:.' \ |
|||
'Child \$HOME = '^$HOME \ |
|||
'Child \$USER = '^$USER \ |
|||
'Child \$ROOT = \(null\)' \ |
|||
'Child \$TEST = value' \ |
|||
'Parent unsetenv\(TEST\); now \$TEST = \(null\)' \ |
|||
PASS ) |
|||
|
|||
for (line in $expected_lines) { |
|||
if ( ! cat $test_output | grep $"line > /dev/null ) { |
|||
cat $test_output |
|||
echo FAIL: can not find line: $line |
|||
exit FAIL |
|||
} |
|||
} |
|||
echo PASS |
|||
exit PASS |
@ -0,0 +1,48 @@ |
|||
#include <sys/types.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
|
|||
// see http://www.informit.com/articles/article.aspx?p=99706&seqNum=13 |
|||
int |
|||
main(int argc, char *argv[]) |
|||
{ |
|||
|
|||
int fd, accmode, val; |
|||
|
|||
if (argc != 2) |
|||
fd = 0; |
|||
else |
|||
fd = atoi(argv[1]); |
|||
|
|||
if ( (val = fcntl(fd, F_GETFL, 0)) < 0){ |
|||
perror("fcntl error for fd"); |
|||
exit(1); |
|||
} |
|||
|
|||
printf("fcntl(%d) returns %d\n", fd, val); |
|||
|
|||
accmode = val & O_ACCMODE; |
|||
if (accmode == O_RDONLY) |
|||
printf("read only"); |
|||
else if (accmode == O_WRONLY) |
|||
printf("write only"); |
|||
else if (accmode == O_RDWR) |
|||
printf("read write"); |
|||
else { |
|||
perror("unknown access mode"); |
|||
exit(1); |
|||
} |
|||
|
|||
if (val & O_APPEND) |
|||
printf(", append"); |
|||
if (val & O_NONBLOCK) |
|||
printf(", nonblocking"); |
|||
#if !defined(_POSIX_SOURCE) && defined(O_SYNC) |
|||
if (val & O_SYNC) |
|||
printf(", synchronous writes"); |
|||
#endif |
|||
putchar('\n'); |
|||
exit(0); |
|||
} |
@ -0,0 +1,82 @@ |
|||
#include <sys/types.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
|
|||
void |
|||
fail_if_still_open(int fd) |
|||
{ |
|||
if(fd == 0){ |
|||
printf("atoi failed\n"); |
|||
exit(2); |
|||
} |
|||
if(fcntl(fd, F_GETFD) != -1){ |
|||
printf("fd %d is still open\n", fd); |
|||
exit(3); |
|||
} |
|||
} |
|||
|
|||
int |
|||
main(int argc, char *argv[]) |
|||
{ |
|||
int sync[2]; |
|||
int outfd; |
|||
int nullfd; |
|||
int tmp; |
|||
char *eargv[7], *p; |
|||
char buf[128]; |
|||
|
|||
if(argc == 1){ |
|||
printf("cat /proc/%d/fd\n", getpid()); |
|||
|
|||
pipe(sync); |
|||
outfd = dup(1); |
|||
nullfd = open("/dev/null", O_WRONLY); |
|||
tmp = fcntl(sync[0], F_DUPFD_CLOEXEC, 1); |
|||
close(sync[0]); |
|||
sync[0] = tmp; |
|||
tmp = fcntl(sync[1], F_DUPFD_CLOEXEC, 1); |
|||
close(sync[1]); |
|||
sync[1] = tmp; |
|||
tmp = fcntl(outfd, F_DUPFD_CLOEXEC, 1); |
|||
close(outfd); |
|||
outfd = tmp; |
|||
tmp = fcntl(nullfd, F_DUPFD_CLOEXEC, 1); |
|||
close(nullfd); |
|||
nullfd = tmp; |
|||
|
|||
eargv[0] = argv[0]; |
|||
p = buf; |
|||
eargv[1] = p; |
|||
p += 1+sprintf(p, "%d", sync[0]); |
|||
eargv[2] = p; |
|||
p += 1+sprintf(p, "%d", sync[1]); |
|||
eargv[3] = p; |
|||
p += 1+sprintf(p, "%d", outfd); |
|||
eargv[4] = p; |
|||
p += 1+sprintf(p, "%d", nullfd); |
|||
eargv[5] = NULL; |
|||
|
|||
execvp(argv[0], eargv); |
|||
printf("execvp returned\n"); |
|||
exit(100); |
|||
|
|||
} else if(argc != 5){ |
|||
printf("argc = %d (should be 5)\n", argc); |
|||
exit(1); |
|||
} |
|||
|
|||
printf("argc = %d; fds: %s %s %s %s\n", argc, argv[1], argv[2], argv[3], argv[4] ); |
|||
sync[0] = atoi(argv[1]); |
|||
sync[1] = atoi(argv[2]); |
|||
outfd = atoi(argv[3]); |
|||
nullfd = atoi(argv[4]); |
|||
|
|||
fail_if_still_open(sync[0]); |
|||
fail_if_still_open(sync[1]); |
|||
fail_if_still_open(outfd); |
|||
fail_if_still_open(nullfd); |
|||
|
|||
exit(0); |
|||
} |
@ -0,0 +1,51 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
|
|||
void sigusr1() { |
|||
printf("Got SIGUSR1\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
int |
|||
main() |
|||
{ |
|||
sigset_t old_set, new_set; |
|||
sigemptyset(&old_set); |
|||
sigemptyset(&new_set); |
|||
|
|||
signal(SIGUSR1, sigusr1); |
|||
|
|||
if(sigaddset(&new_set, SIGSEGV) == 0) |
|||
{ |
|||
printf("sigaddset successfully added for SIGSEGV\n"); |
|||
} |
|||
sigprocmask(SIG_BLOCK, &new_set, &old_set); |
|||
|
|||
printf("raise(SIGSEGV)\n"); |
|||
raise(SIGSEGV); |
|||
|
|||
if(sigaddset(&new_set, SIGUSR1) == 0) |
|||
{ |
|||
printf("sigaddset successfully added for SIGUSR1\n"); |
|||
} |
|||
if(sigprocmask(SIG_BLOCK, &new_set, &old_set) == -1) |
|||
{ |
|||
perror("sigprocmask"); |
|||
} |
|||
|
|||
printf("raise(SIGUSR1)\n"); |
|||
raise(SIGUSR1); |
|||
|
|||
sigemptyset(&new_set); |
|||
sigaddset(&new_set, SIGUSR1); |
|||
|
|||
printf("unblock SIGUSR1 via sigprocmask\n"); |
|||
if(sigprocmask(SIG_UNBLOCK, &new_set, &old_set) == -1) |
|||
{ |
|||
perror("sigprocmask"); |
|||
} |
|||
|
|||
return 1; |
|||
} |
@ -0,0 +1,74 @@ |
|||
#define _POSIX_SOURCE |
|||
#include <stdio.h> |
|||
#include <signal.h> |
|||
#include <time.h> |
|||
#include <unistd.h> |
|||
#include <stdlib.h> |
|||
|
|||
int SIGUSR1_caught; |
|||
int SIGUSR2_caught; |
|||
|
|||
void catcher(int signum) { |
|||
switch (signum) { |
|||
case SIGUSR1: |
|||
++SIGUSR1_caught; |
|||
puts("catcher caught SIGUSR1"); |
|||
if(SIGUSR2_caught){ |
|||
puts("FAIL: SIGUSR2 already caught"); |
|||
exit(1); |
|||
} |
|||
break; |
|||
case SIGUSR2: |
|||
++SIGUSR2_caught; |
|||
puts("catcher caught SIGUSR2"); |
|||
break; |
|||
default: |
|||
printf("catcher caught unexpected signal %d\n", signum); |
|||
} |
|||
} |
|||
|
|||
int |
|||
main() |
|||
{ |
|||
sigset_t sigset; |
|||
struct sigaction sact; |
|||
time_t t; |
|||
|
|||
if (fork() == 0) { |
|||
printf("child is %d\n", getpid()); |
|||
sleep(10); |
|||
puts("child is sending SIGUSR2 signal - which should be blocked"); |
|||
kill(getppid(), SIGUSR2); |
|||
sleep(5); |
|||
puts("child is sending SIGUSR1 signal - which should be caught"); |
|||
kill(getppid(), SIGUSR1); |
|||
exit(0); |
|||
} |
|||
|
|||
sigemptyset(&sact.sa_mask); |
|||
sact.sa_flags = 0; |
|||
sact.sa_handler = catcher; |
|||
|
|||
if (sigaction(SIGUSR1, &sact, NULL) != 0) |
|||
perror("1st sigaction() error"); |
|||
else if (sigaction(SIGUSR2, &sact, NULL) != 0) |
|||
perror("2nd sigaction() error"); |
|||
else { |
|||
sigfillset(&sigset); |
|||
sigdelset(&sigset, SIGUSR1); |
|||
time(&t); |
|||
printf("parent is waiting for child to send SIGUSR1 at %s", |
|||
ctime(&t)); |
|||
if (sigsuspend(&sigset) == -1) |
|||
perror("sigsuspend() returned -1 as expected"); |
|||
time(&t); |
|||
printf("sigsuspend is over at %s", ctime(&t)); |
|||
} |
|||
if(SIGUSR1_caught != 1) |
|||
printf("SIGUSR1_caught is %d\n", SIGUSR1_caught); |
|||
if(SIGUSR2_caught != 1) |
|||
printf("SIGUSR2_caught is %d\n", SIGUSR2_caught); |
|||
if(SIGUSR1_caught != 1 || SIGUSR2_caught != 1) |
|||
exit(2); |
|||
exit(0); |
|||
} |
@ -0,0 +1,69 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
|
|||
void catcher(int sig) { |
|||
puts("Got SIGUSR1"); |
|||
} |
|||
|
|||
int check_pending(int sig, char *signame) { |
|||
|
|||
sigset_t sigset; |
|||
|
|||
if(sigpending(&sigset) != 0){ |
|||
perror("sigpending() error\n"); |
|||
exit(1); |
|||
} |
|||
if(sigismember(&sigset, sig)){ |
|||
printf("a %s (%d) signal is pending\n", signame, sig); |
|||
return 1; |
|||
} else { |
|||
printf("no %s (%d) signals are pending\n", signame, sig); |
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
struct sigaction sigact; |
|||
sigset_t sigset; |
|||
|
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
|
|||
if(sigaction(SIGUSR1, &sigact, NULL) != 0){ |
|||
perror("sigaction() error\n"); |
|||
return 2; |
|||
} |
|||
|
|||
printf("Calling sigprocmask to block SIGUSR1...\n"); |
|||
sigemptyset(&sigset); |
|||
sigaddset(&sigset, SIGUSR1); |
|||
if (sigprocmask(SIG_SETMASK, &sigset, NULL) != 0){ |
|||
perror("sigprocmask() error\n"); |
|||
return 3; |
|||
} |
|||
printf("SIGUSR1 signals are now blocked\n"); |
|||
|
|||
kill(getpid(), SIGUSR1); |
|||
printf("kill(getpid(), SIGUSR1) DONE\n"); |
|||
|
|||
if(!check_pending(SIGUSR1, "SIGUSR1")){ |
|||
printf("FAIL: SIGUSR1 is not pending despite the mask\n"); |
|||
return 4; |
|||
} |
|||
|
|||
printf("Calling sigprocmask to unblock SIGUSR1...\n"); |
|||
sigemptyset(&sigset); |
|||
sigprocmask(SIG_SETMASK, &sigset, NULL); |
|||
printf("SIGUSR1 signals are no longer blocked\n"); |
|||
|
|||
if(check_pending(SIGUSR1, "SIGUSR1")){ |
|||
printf("FAIL: SIGUSR1 is still pending despite the mask\n"); |
|||
return 4; |
|||
} |
|||
|
|||
return 0; |
|||
} |
@ -0,0 +1,54 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
|
|||
void catcher(int sig) { |
|||
printf("Signal catcher called for signal %d\n", sig); |
|||
} |
|||
|
|||
void timestamp(char *str) { |
|||
time_t t; |
|||
|
|||
time(&t); |
|||
printf("The time %s is %s", str, ctime(&t)); |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
int result = 0; |
|||
int err = 0; |
|||
|
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
siginfo_t info; |
|||
|
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
sigaction(SIGALRM, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGALRM); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
alarm(3); |
|||
|
|||
timestamp("before sigwaitinfo()"); |
|||
|
|||
result = sigwaitinfo(&waitset, &info); |
|||
err = errno; |
|||
|
|||
timestamp("after sigwaitinfo()"); |
|||
|
|||
if(result > 0){ |
|||
printf("sigwaitinfo() returned for signal %d\n", info.si_signo); |
|||
return 0; |
|||
} |
|||
|
|||
printf("sigwaitinfo() returned %d; errno = %d\n", result, err); |
|||
perror("sigwaitinfo() function failed"); |
|||
return 1; |
|||
} |
@ -0,0 +1,58 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
|
|||
void catcher(int sig) { |
|||
printf("Signal catcher called for signal %d\n", sig); |
|||
} |
|||
|
|||
void timestamp(char *str) { |
|||
time_t t; |
|||
|
|||
time(&t); |
|||
printf("The time %s is %s\n", str, ctime(&t)); |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
int result = 0; |
|||
int err = 0; |
|||
|
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
siginfo_t info; |
|||
struct timespec timeout; |
|||
|
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
sigaction(SIGALRM, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGALRM); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
timeout.tv_sec = 4; /* Number of seconds to wait */ |
|||
timeout.tv_nsec = 1000; /* Number of nanoseconds to wait */ |
|||
|
|||
alarm(2); |
|||
|
|||
timestamp("before sigtimedwait()"); |
|||
|
|||
result = sigtimedwait(&waitset, &info, &timeout); |
|||
err = errno; |
|||
|
|||
timestamp("after sigtimedwait()"); |
|||
|
|||
if(result > 0){ |
|||
printf("sigtimedwait() returned for signal %d\n", info.si_signo); |
|||
return 0; |
|||
} |
|||
|
|||
printf("sigtimedwait() returned %d; errno = %d\n", result, err); |
|||
perror("sigtimedwait() function failed"); |
|||
return 1; |
|||
} |
@ -0,0 +1,61 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
|
|||
void catcher(int sig) { |
|||
printf("Signal catcher called for signal %d\n", sig); |
|||
} |
|||
|
|||
void timestamp(char *str) { |
|||
time_t t; |
|||
|
|||
time(&t); |
|||
printf("The time %s is %s\n", str, ctime(&t)); |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
int result = 0; |
|||
int err = 0; |
|||
|
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
siginfo_t info; |
|||
struct timespec timeout; |
|||
|
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
sigaction(SIGALRM, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGALRM); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
timeout.tv_sec = 1; /* Number of seconds to wait */ |
|||
timeout.tv_nsec = 1000; /* Number of nanoseconds to wait */ |
|||
|
|||
alarm(4); |
|||
|
|||
timestamp("before sigtimedwait()"); |
|||
|
|||
result = sigtimedwait(&waitset, &info, &timeout); |
|||
err = errno; |
|||
|
|||
timestamp("after sigtimedwait()"); |
|||
|
|||
if(result > 0){ |
|||
printf("sigtimedwait() returned for signal %d\n", info.si_signo); |
|||
return 1; |
|||
} |
|||
|
|||
printf("sigtimedwait() returned %d; errno = %d\n", result, err); |
|||
if(err != EAGAIN){ |
|||
perror("errno is not EAGAIN"); |
|||
return 2; |
|||
} |
|||
return 0; |
|||
} |
@ -0,0 +1,54 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
|
|||
void catcher(int sig) { |
|||
printf("Signal catcher called for signal %d\n", sig); |
|||
} |
|||
|
|||
void timestamp(char *str) { |
|||
time_t t; |
|||
|
|||
time(&t); |
|||
printf("The time %s is %s", str, ctime(&t)); |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
int result = 0; |
|||
int err = 0; |
|||
|
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
int sig; |
|||
|
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
sigaction(SIGALRM, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGALRM); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
alarm(3); |
|||
|
|||
timestamp("before sigwait()"); |
|||
|
|||
result = sigwait(&waitset, &sig); |
|||
err = errno; |
|||
|
|||
timestamp("after sigwait()"); |
|||
|
|||
if(result == 0){ |
|||
printf("sigwait() returned for signal %d\n", sig); |
|||
return 0; |
|||
} |
|||
|
|||
printf("sigwait() returned %d; errno = %d\n", result, err); |
|||
perror("sigwait() function failed"); |
|||
return 1; |
|||
} |
@ -0,0 +1,88 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <time.h> |
|||
#include <errno.h> |
|||
#include <stdlib.h> |
|||
|
|||
void catcher(int sig, siginfo_t *info, void *p) { |
|||
printf("Signal catcher called for signal %d from %d\n", sig, info->si_pid); |
|||
exit(1); |
|||
} |
|||
|
|||
void timestamp(char *str) { |
|||
time_t t; |
|||
|
|||
time(&t); |
|||
printf("The time %s is %s", str, ctime(&t)); |
|||
} |
|||
|
|||
void echoSIGUSR1(void){ |
|||
int result; |
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
siginfo_t info; |
|||
union sigval v; |
|||
|
|||
printf("CHILD pid %d\n", getpid()); |
|||
v.sival_int = 0; |
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = SA_SIGINFO; |
|||
sigact.sa_sigaction = catcher; |
|||
sigaction(SIGUSR1, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGUSR1); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
while(v.sival_int < 5){ |
|||
result = sigwaitinfo(&waitset, &info); |
|||
v.sival_int = 1 + info.si_value.sival_int; |
|||
printf("CHILD sigqueue %d to %d\n", v.sival_int, info.si_pid); |
|||
sigqueue(info.si_pid, result, v); |
|||
} |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
int result; |
|||
struct sigaction sigact; |
|||
sigset_t waitset; |
|||
siginfo_t info; |
|||
union sigval v; |
|||
pid_t child; |
|||
|
|||
switch(child = fork()){ |
|||
case 0: |
|||
echoSIGUSR1(); |
|||
exit(0); |
|||
break; |
|||
case -1: |
|||
exit(1); |
|||
break; |
|||
default: |
|||
break; |
|||
} |
|||
|
|||
printf("PARENT pid %d sleep(3)\n", getpid()); |
|||
sleep(3); |
|||
v.sival_int = 0; |
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = SA_SIGINFO; |
|||
sigact.sa_sigaction = catcher; |
|||
sigaction(SIGUSR1, &sigact, NULL); |
|||
|
|||
sigemptyset(&waitset); |
|||
sigaddset(&waitset, SIGUSR1); |
|||
|
|||
sigprocmask(SIG_BLOCK, &waitset, NULL); |
|||
|
|||
result = SIGUSR1; |
|||
do{ |
|||
printf("PARENT sigqueue %d\n", v.sival_int); |
|||
sigqueue(child, result, v); |
|||
result = sigwaitinfo(&waitset, &info); |
|||
v.sival_int = 1 + info.si_value.sival_int; |
|||
} while(v.sival_int < 5); |
|||
exit(0); |
|||
} |
@ -0,0 +1,132 @@ |
|||
#include <signal.h> |
|||
#include <setjmp.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
|
|||
sigset_t sigset; |
|||
sigjmp_buf mark; |
|||
int catcherWasCalled; |
|||
|
|||
void catcher(int); |
|||
void p(void); |
|||
|
|||
int main(int argc, char *argv[]) { |
|||
|
|||
int result = 0; |
|||
int returnCode = 0; |
|||
|
|||
/* |
|||
* Block the SIGUSR2 signal. This signal set will be |
|||
* saved as part of the environment by the sigsetjmp() |
|||
* function and subsequently restored by the siglongjmp() |
|||
* function. |
|||
*/ |
|||
|
|||
sigemptyset(&sigset); |
|||
sigaddset(&sigset, SIGUSR2); |
|||
sigprocmask(SIG_SETMASK, &sigset, NULL); |
|||
|
|||
/* Save the stack environment and the current signal mask */ |
|||
|
|||
returnCode = sigsetjmp(mark, 1); |
|||
|
|||
/* Handle the sigsetjmp return code */ |
|||
|
|||
switch(returnCode) { |
|||
case 0: |
|||
printf("sigsetjmp() has been called\n"); |
|||
|
|||
/* |
|||
* Call function p() which will call the siglongjmp() |
|||
* function |
|||
*/ |
|||
p(); |
|||
|
|||
printf("control returning here is an error\n"); |
|||
result=-1; |
|||
break; |
|||
case -1: |
|||
printf("siglongjmp() function was called\n"); |
|||
|
|||
/* Retrieve the current signal mask */ |
|||
|
|||
sigprocmask(SIG_SETMASK, NULL, &sigset); |
|||
|
|||
/* Verify SIGUSR2 is in sigset */ |
|||
if(sigismember(&sigset, SIGUSR2)) { |
|||
printf("signal mask was restored after siglongjmp()\n"); |
|||
result=0; |
|||
} else { |
|||
printf("signal mask was not restored after siglongjmp()\n"); |
|||
result=-1; |
|||
} |
|||
break; |
|||
default: |
|||
printf("this unexpected return code is an error\n"); |
|||
result=-1; |
|||
break; |
|||
} |
|||
|
|||
printf("return from main with result %d\n", result); |
|||
|
|||
return result; |
|||
} |
|||
|
|||
void p(void) { |
|||
|
|||
struct sigaction sigact; |
|||
int error=0; |
|||
|
|||
printf("performing function p()\n"); |
|||
|
|||
/* Setup signal handler in case error condition is detected */ |
|||
sigemptyset(&sigact.sa_mask); |
|||
sigact.sa_flags = 0; |
|||
sigact.sa_handler = catcher; |
|||
sigaction(SIGUSR2, &sigact, NULL); |
|||
|
|||
/* |
|||
* Delete SIGUSR2 from the signal set that was initialized |
|||
* by the main() function. This allows us to demonstrate |
|||
* that the original signal set saved by the sigsetjmp() function |
|||
* is restored by the siglongjmp() function. |
|||
*/ |
|||
sigdelset(&sigset, SIGUSR2); |
|||
sigprocmask(SIG_SETMASK, &sigset, NULL); |
|||
|
|||
/* After some processing an error condition is detected */ |
|||
error=-1; |
|||
|
|||
/* Call catcher() function if error is detected */ |
|||
if(error != 0) { |
|||
catcherWasCalled = 0; |
|||
|
|||
/* Send SIGUSR2 to handle the error condition */ |
|||
|
|||
printf("error condition detected, send SIGUSR2 signal\n"); |
|||
kill(getpid(), SIGUSR2); |
|||
|
|||
if(catcherWasCalled == 1) { |
|||
printf("catcher() function handled the error condition\n"); |
|||
|
|||
/* |
|||
* Perform a nonlocal "goto" and specify -1 for the |
|||
* return value |
|||
*/ |
|||
|
|||
siglongjmp(mark, -1); |
|||
|
|||
printf("control getting here is an error\n"); |
|||
exit(3); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void catcher(int signo) { |
|||
/* |
|||
* Indicate the catcher() function is handling the |
|||
* SIGUSR2 signal. |
|||
*/ |
|||
catcherWasCalled = 1; |
|||
} |
@ -0,0 +1,38 @@ |
|||
#include <signal.h> |
|||
#include <unistd.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <sys/wait.h> |
|||
|
|||
sigset_t parent_mask; |
|||
|
|||
int |
|||
main() |
|||
{ |
|||
int status; |
|||
sigset_t mask; |
|||
|
|||
sigprocmask(SIG_BLOCK, NULL, &parent_mask); |
|||
sigaddset(&parent_mask, SIGSEGV); |
|||
sigprocmask(SIG_BLOCK, &parent_mask, NULL); |
|||
printf("SIGSEGV blocked in parent. Forking...\n"); |
|||
|
|||
switch(fork()){ |
|||
case -1: |
|||
exit(1); |
|||
case 0: |
|||
sigprocmask(SIG_BLOCK, NULL, &mask); |
|||
printf("Is SIGSEGV (%llx) a member of %llx?\n", 1ULL<<(SIGSEGV-1), (long long unsigned int)mask); |
|||
if(sigismember(&mask, SIGSEGV) != 1){ |
|||
printf("FAIL: SIGSEGV is not present in child's mask after fork\n"); |
|||
exit(2); |
|||
} |
|||
printf("PASS\n"); |
|||
exit(0); |
|||
default: |
|||
wait(&status); |
|||
status = WEXITSTATUS(status); |
|||
exit(status); |
|||
} |
|||
|
|||
} |