libposix: deep refactor; add sys/posixly command

With these changes, libposix (and newlib) can run MirBSD Korn Shell.
This commit is contained in:
Giacomo Tesio 2017-09-11 01:01:11 +02:00
parent 2f99fb162f
commit 001069aa7b
56 changed files with 4939 additions and 608 deletions

2
cfg/mksh/profile Normal file
View File

@ -0,0 +1,2 @@
export PWD=`cat /dev/wdir`
export HOSTNAME=$SYSNAME

View File

@ -2,6 +2,11 @@
rfork
if( ! test -d /dev/posix ){
sys/posixly -d /tmp/qa-posixly.log -p $PID &
# sys/ctrace -o /tmp/posixly.trace $APID &
}
dir=$1
if(~ $dir '') dir=/qa

View File

@ -74,7 +74,7 @@ main(void)
elapsed = (nsec() - start) / (1000 * 1000);
if(verbose)
fprint(2, "rendezvous interrupted, returned %#p, elapsed = %d ms\n", res, elapsed);
if(!awakened(wkup) || elapsed < 900 || elapsed > 1300){
if(!awakened(wkup) || elapsed < 900 || elapsed > 1800){
print("FAIL: rendezvous\n");
exits("FAIL");
}
@ -105,7 +105,7 @@ main(void)
elapsed = (nsec() - start) / (1000 * 1000);
if(verbose)
print("semacquire(&sem, 1): returned %lld, elapsed = %d ms\n", res, elapsed);
if(!awakened(wkup) || res != -1 || elapsed < 900 || elapsed > 1300){
if(!awakened(wkup) || res != -1 || elapsed < 900 || elapsed > 1800){
print("FAIL: semacquire\n");
exits("FAIL");
}
@ -113,8 +113,8 @@ main(void)
/* verify that tsemacquire are NOT interrupted */
fprint(2, "verify that tsemacquire are NOT interrupted\n", elapsed);
wkup = awake(700);
start = nsec();
wkup = awake(500);
res = tsemacquire(&sem, 1500);
elapsed = (nsec() - start) / (1000 * 1000);
if(verbose)
@ -137,7 +137,7 @@ main(void)
elapsed = (nsec() - start) / (1000 * 1000);
if(verbose)
fprint(2, "read(fds[0], buf, 1) returned %lld, elapsed = %d ms\n", res, elapsed);
if(!awakened(wkup) || res != -1 || elapsed < 900 || elapsed > 1300){
if(!awakened(wkup) || res != -1 || elapsed < 900 || elapsed > 1800){
print("FAIL: read\n");
exits("FAIL");
}
@ -155,7 +155,7 @@ main(void)
elapsed = (nsec() - start) / (1000 * 1000);
if(verbose)
fprint(2, "writeTillBlock(fds[0]) returned %lld, elapsed = %d ms\n", res, elapsed);
if(!awakened(wkup) || res >= 256 || elapsed < 900 || elapsed > 1300){
if(!awakened(wkup) || res >= 256 || elapsed < 900 || elapsed > 1800){
print("FAIL: write\n");
exits("FAIL");
}

View File

@ -208,7 +208,7 @@ main(int argc, char* argv[])
}
average = average / NPROC / (1000 * 1000);
if(average < 300) /* we asked for 1ms... we are dumb, after all */
if(average < 1000) /* we asked for 1ms... we are dumb, after all */
{
print("PASS\n");
exits("PASS");

View File

@ -112,7 +112,7 @@ waiter(int index)
if(verbose)
print("reader %d: got the rlock in %lld ms\n", getpid(), (end - start) / (1000*1000));
runlock(&afterAWhile);
if((end - start) / (1000*1000) > 1500)
if((end - start) / (1000*1000) > 2000)
postnote(PNGROUP, getpid(), smprint("fail: reader %d got the rlock after %lld ms", getpid(), (end - start) / (1000*1000)));
} else {
if(verbose)
@ -127,7 +127,7 @@ waiter(int index)
rwakeup(&rCompleted);
qunlock(&rl);
return (end - start) / (1000*1000) < 1300 ? nil : "FAIL";
return (end - start) / (1000*1000) < 2000 ? nil : "FAIL";
}
void

View File

@ -214,7 +214,7 @@ main(int argc, char* argv[])
}
average = average / NPROC / (1000 * 1000);
if(average < 300) /* we asked for 1ms... we are dumb, after all */
if(average < 800) /* we asked for 1ms... we are dumb, after all */
{
print("PASS\n");
exits("PASS");

View File

@ -215,7 +215,7 @@ main(int argc, char* argv[])
}
average = average / NPROC / (1000 * 1000);
if(average < 500) /* we asked for 1ms... we are dumb, after all */
if(average < 1000) /* we asked for 1ms... we are dumb, after all */
{
print("PASS\n");
exits("PASS");

View File

@ -210,7 +210,7 @@ main(int argc, char* argv[])
}
average = average / NPROC / (1000 * 1000);
if(average < 300) /* we asked for 1ms... we are dumb, after all */
if(average < 1000) /* we asked for 1ms... we are dumb, after all */
{
print("PASS\n");
exits("PASS");

View File

@ -0,0 +1,7 @@
#include <stdio.h>
int main()
{
fprintf(stdout, "hello, stdout\n");
fprintf(stderr, "hello, stderr\n");
return 0;
}

View File

@ -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;
}

44
qa/lib/newlib/041-env.c Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -11,43 +11,46 @@ main(int argc, char **argv)
int p[2], ppgrp, opgrp, npgrp;
char c = '?';
if (pipe(p) != 0)
if (pipe(p) != 0){
perror("pipe() error");
else {
ppgrp = getpgrp();
printf("parent's pid %d; process group id %d\n", getpid(), ppgrp);
if ((pid = fork()) == 0) {
opgrp = getpgrp();
printf("child's pid %d; process group id %d\n", getpid(), opgrp);
write(p[1], &c, 1);
setsid();
npgrp = getpgrp();
if(opgrp == npgrp){
printf("FAIL: setsid did not changed child's process group id\n");
exit(EXIT_FAILURE);
}
printf("child's process group id is now %d\n", npgrp);
sleep(5);
exit(EXIT_SUCCESS);
} else {
read(p[0], &c, 1);
sleep(3);
if(ppgrp != getpgrp()){
printf("FAIL: parent's process group id changed from %d to %d\n", ppgrp, getpgrp());
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
ppgrp = getpgrp();
printf("parent's pid %d; process group id %d\n", getpid(), ppgrp);
if ((pid = fork()) == 0) {
opgrp = getpgrp();
printf("child's pid %d; process group id %d\n", getpid(), opgrp);
if(setsid() == -1){
write(p[1], "e", 1);
perror("FAIL: setsid");
exit(EXIT_FAILURE);
}
write(p[1], &c, 1);
npgrp = getpgrp();
if(opgrp == npgrp){
printf("FAIL: setsid did not changed child's process group id\n");
exit(EXIT_FAILURE);
}
printf("child's process group id is now %d\n", npgrp);
sleep(5);
exit(EXIT_SUCCESS);
} else {
read(p[0], &c, 1);
sleep(3);
if(c == 'e')
exit(EXIT_FAILURE);
if(ppgrp != getpgrp()){
printf("FAIL: parent's process group id changed from %d to %d\n", ppgrp, getpgrp());
exit(EXIT_FAILURE);
}
#ifndef WITH_SIGCHLD
npgrp = getsid(pid);
if(npgrp < 0){
printf("FAIL: parent's getsid(%d) failed with errno %d\n", pid, errno);
exit(EXIT_FAILURE);
}
if(npgrp == ppgrp){
printf("FAIL: parent's getsid(%d) returned old process group id that should be changed\n", pid);
exit(EXIT_FAILURE);
}
#endif
npgrp = getsid(pid);
if(npgrp == ppgrp){
printf("FAIL: parent's getsid(%d) returned old process group id that should be changed\n", pid);
exit(EXIT_FAILURE);
}
#endif
exit(EXIT_SUCCESS);
}
}

View File

@ -5,7 +5,7 @@ test_output = /tmp/output-`{basename $test}
if ( test -e $test_output) rm $test_output
$test $test_output > /dev/null
$test > $test_output
if ( cat $test_output | grep 'FAIL' > /dev/null ) {
cat $test_output
echo FAIL

48
qa/lib/newlib/120-fcntl.c Normal file
View File

@ -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);
}

82
qa/lib/newlib/121-fcntl.c Normal file
View File

@ -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);
}

View File

@ -58,6 +58,7 @@ main() {
signal(SIGQUIT, sigquit);
printf("\nChild going to loop...\n\n");
write(p[1], "", 1);
close(p[1]);
close(p[0]);
for(;;); /* loop for ever */
@ -65,11 +66,11 @@ main() {
else /* parent */
{
signal(SIGCHLD,sigchld);
close(p[1]);
if(read(p[0], &dummy, 1) > 0){
printf("sync read received data");
if(read(p[0], &dummy, 1) != 1){
printf("sync read");
exit(EXIT_FAILURE);
}
close(p[1]);
close(p[0]);
printf("\nPARENT: sending SIGHUP\n\n");
kill(pid,SIGHUP);

View File

@ -26,6 +26,7 @@ main() {
if (pid == 0) {
printf("\nI am the new child!\n\n");
write(p[1], "", 1);
close(p[1]);
close(p[0]);
for(;;){
@ -36,11 +37,11 @@ main() {
}
else /* parent */
{
close(p[1]);
if(read(p[0], &dummy, 1) > 0){
printf("sync read received data");
if(read(p[0], &dummy, 1) != 1){
printf("sync read");
exit(EXIT_FAILURE);
}
close(p[1]);
close(p[0]);
printf("\nPARENT: sending SIGINT\n\n");
kill(pid,SIGINT);

View File

@ -28,6 +28,7 @@ main() {
if (pid == 0) {
signal(SIGCONT,sigcont); /* set function calls */
printf("Child going to loop...\n");
write(p[1], "", 1);
close(p[1]);
close(p[0]);
for(;;){
@ -38,11 +39,8 @@ main() {
}
else /* parent */
{
read(p[0], &dummy, 1);
close(p[1]);
if(read(p[0], &dummy, 1) > 0){
printf("sync read received data");
exit(EXIT_FAILURE);
}
close(p[0]);
printf("PARENT: sending SIGCONT\n\n");
kill(pid,SIGCONT);

View File

@ -22,7 +22,8 @@ void childloop(void)
{
signal(SIGCONT,sigcont); /* set function calls */
signal(SIGSTOP,sigstop); /* set function calls */
printf("Child going to loop...\n");
printf("Child %d going to loop...\n", getpid());
write(p[1], "", 1);
close(p[1]);
close(p[0]);
for(;;){
@ -54,11 +55,8 @@ main() {
}
else /* parent */
{
read(p[0], &dummy, 1);
close(p[1]);
if(read(p[0], &dummy, 1) > 0){
printf("sync read received data");
exit(EXIT_FAILURE);
}
close(p[0]);
sleep(2);
printf("PARENT: sending SIGSTOP\n");

View File

@ -47,6 +47,7 @@ main() {
signal(SIGQUIT, sigquit);
printf("Child going to loop...\n");
write(p[1], "", 1);
close(p[1]);
close(p[0]);
for(;;); /* loop for ever */
@ -54,11 +55,8 @@ main() {
else /* parent */
{
signal(SIGCHLD,sigchld);
read(p[0], &dummy, 1);
close(p[1]);
if(read(p[0], &dummy, 1) > 0){
printf("sync read received data");
exit(EXIT_FAILURE);
}
close(p[0]);
printf("PARENT: sending SIGHUP\n");
kill(pid,SIGHUP);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -32,22 +32,37 @@
],
"SourceFilesCmd": [
"000-hello.c",
"001-hello.c",
"002-atexit.c",
"010-fork.c",
"020-waitpid.c",
"030-pause.c",
"031-setjmp.c",
"040-gettimeofday.c",
"041-env.c",
"050-setsid.c",
"100-files.c",
"101-files.c",
"102-files.c",
"103-files.c",
"120-fcntl.c",
"121-fcntl.c",
"200-signals.c",
"201-signals.c",
"202-signals.c",
"203-signals.c",
"204-signals.c",
"205-signals.c"
"205-signals.c",
"206-signals.c",
"207-sigsuspend.c",
"208-sigpending.c",
"209-sigwaitinfo.c",
"210-sigtimedwait.c",
"211-sigtimedwait.c",
"212-sigwait.c",
"213-sigqueue.c",
"214-sigsetjmp.c",
"215-sigprocmask.c"
]
},
"SIGCHLDTests": {
@ -84,20 +99,37 @@
],
"SourceFilesCmd": [
"000-hello.c",
"001-hello.c",
"002-atexit.c",
"010-fork.c",
"020-waitpid.c",
"030-pause.c",
"031-setjmp.c",
"040-gettimeofday.c",
"041-env.c",
"050-setsid.c",
"100-files.c",
"101-files.c",
"102-files.c",
"103-files.c",
"120-fcntl.c",
"121-fcntl.c",
"200-signals.c",
"201-signals.c",
"202-signals.c",
"203-signals.c",
"204-signals.c",
"205-signals.c"
"205-signals.c",
"206-signals.c",
"207-sigsuspend.c",
"208-sigpending.c",
"209-sigwaitinfo.c",
"210-sigtimedwait.c",
"211-sigtimedwait.c",
"212-sigwait.c",
"213-sigqueue.c",
"214-sigsetjmp.c",
"215-sigprocmask.c"
]
},
"NewlibTestsuite": {

View File

@ -27,18 +27,34 @@ qa_exit_translator(int status)
* should return PASS/FAIL
*/