diff --git a/tests/Makefile b/tests/Makefile index 38412a55ce..32f2725fe2 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -29,14 +29,12 @@ EXPECT_NAMES=\ locale \ math \ netdb/getaddrinfo \ - ptrace \ regex \ select \ setjmp \ sigaction \ sigaltstack \ signal \ - sigsetjmp \ stdio/all \ stdio/buffer \ stdio/dprintf \ @@ -122,7 +120,6 @@ EXPECT_NAMES=\ unistd/fsync \ unistd/ftruncate \ unistd/getopt \ - unistd/getopt_long \ unistd/pipe \ unistd/rmdir \ waitpid \ @@ -130,6 +127,7 @@ EXPECT_NAMES=\ kill-waitpid \ # unistd/sleep \ unistd/swab \ + unistd/getopt_long \ unistd/write \ wchar/fgetwc \ wchar/fwide \ @@ -183,6 +181,59 @@ NAMES=\ pwd \ sa_restart \ sigchld \ + signals/kill-self \ + signals/kill0-self \ + signals/kill-invalid \ + signals/kill-permission \ + signals/killpg-esrch \ + signals/killpg-invalid \ + signals/killpg0-self \ + signals/kill-group \ + signals/kill-child \ + signals/killpg-child \ + signals/killpg-self \ + signals/pthread_kill-invalid \ + signals/pthread_kill-child \ + signals/pthread_kill-self \ + signals/pthread_kill0-self \ + signals/raise-compliance \ + signals/sigismember-invalid \ + signals/sigismember-valid \ + signals/sigaddset-add \ + signals/sigdelset-delete \ + signals/signal-h \ + signals/signal-h-2 \ + signals/signal-handle_return \ + signals/signal-handler \ + signals/signal-handler2 \ + signals/signal-ignore \ + signals/signal-invalid \ + signals/signal-uncatchable \ + signals/sigprocmask-3 \ + signals/sigprocmask-4 \ + signals/sigprocmask-5 \ + signals/sigprocmask-6 \ + signals/sigprocmask-7 \ + signals/sigprocmask-8 \ + signals/sigprocmask-9 \ + signals/sigprocmask-10 \ + signals/sigprocmask-11 \ + signals/sigprocmask-12 \ + signals/sigpause-invalid \ + signals/sigpause-revert \ + signals/sigpause-suspend \ + signals/sigprocmask-blocksingle \ + signals/sigprocmask-block \ + signals/sigrelse-1 \ + signals/sigrelse-2 \ + signals/sigrelse-3 \ + signals/sigset-1 \ + signals/sigset-10 \ + signals/sigset-2 \ + signals/sigset-3 \ + signals/sigset-4 \ + signals/sigset-5 \ + signals/sigset-9 \ stdio/ctermid \ stdio/tempnam \ stdio/tmpnam \ diff --git a/tests/run_tests.sh b/tests/run_tests.sh index af32abdc75..1af7468a9c 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -168,6 +168,32 @@ STATUS_NAMES=(\ sigchld \ stdio/ctermid \ sigqueue \ + signals/kill-self \ + signals/kill0-self \ + signals/kill-invalid \ + signals/kill-permission \ + signals/killpg-esrch \ + signals/killpg-invalid \ + signals/killpg0-self \ + signals/pthread_kill-invalid \ + signals/pthread_kill0-self \ + signals/raise-compliance \ + signals/sigismember-invalid \ + signals/sigismember-valid \ + signals/signal-handle_return \ + signals/signal-handler \ + signals/signal-handler2 \ + signals/signal-ignore \ + signals/signal-invalid \ + signals/signal-uncatchable \ + signals/sigprocmask-6 \ + signals/sigprocmask-7 \ + signals/sigprocmask-8 \ + signals/sigprocmask-9 \ + signals/sigprocmask-11 \ + signals/sigprocmask-blocksingle \ + signals/sigrelse-2 \ + signals/sigrelse-3 \ stdio/tempnam \ stdio/tmpnam \ stdlib/bsearch \ diff --git a/tests/signals/kill-child.c b/tests/signals/kill-child.c new file mode 100644 index 0000000000..10e332374e --- /dev/null +++ b/tests/signals/kill-child.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +/* + * Test signal catching when being signalled from parent. + * Skip SIGKILL and SIGSTOP as these are not catchable. + */ + +volatile sig_atomic_t sig_handled = 0; + +void sig_handler(int signo) +{ + (void) signo; + sig_handled = 1; +} + +void child_proc(int signum) +{ + sigset_t sig_set; + int status; + + sig_handled = 0; + + status = sigemptyset(&sig_set); + ERROR_IF(sigemptyset, status, == -1); + + status = sigaddset(&sig_set, signum); + ERROR_IF(sigaddset, status, == -1); + + struct sigaction act; + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(signum, &act, NULL); + + status = sleep(10); + ERROR_IF(sleep, status, == 0); + + assert(sig_handled != 0); + + exit(EXIT_SUCCESS); +} + +void parent(int signum, pid_t pid) +{ + int status; + + sleep(1); + status = kill(pid, signum); + ERROR_IF(kill, status, != 0); + + pid = wait(&status); + ERROR_IF(wait, pid, == (pid_t)-1); + + if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SUCCESS) + { + printf("Child did not exit normally.\n"); + exit(EXIT_FAILURE); + } + else + { + return; + } +} + +void kill_child(int signum) +{ + int pid; + + if ((pid = fork()) == 0) + { + child_proc(signum); + } + else + { + parent(signum, pid); + } +} + +int main() +{ + for (long unsigned int i = 1; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + printf("Testing for signal %s (%d)\n", strsignal(sig), sig); + kill_child(sig); + } + return EXIT_SUCCESS; +} diff --git a/tests/signals/kill-group.c b/tests/signals/kill-group.c new file mode 100644 index 0000000000..80059ef874 --- /dev/null +++ b/tests/signals/kill-group.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// this test is to make sure that when a negative pid is supplied to kill, all the processes in that group will be killed + +int handler_called = 0; +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; + return; +} + +int kill_group(int signum) +{ + int pgrp; + struct sigaction act; + int status; + + act.sa_handler=sig_handler; + act.sa_flags=0; + status = sigemptyset(&act.sa_mask); + ERROR_IF(sigemptyset, status, == -1); + + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = getpgrp(); + pgrp = status; + ERROR_IF(getpgrp, status, == -1); + + status = kill(-pgrp, signum); + ERROR_IF(kill, status, != 0); + + ERROR_IF(kill, handler_called, !=1); + handler_called = 0; + + return EXIT_SUCCESS; +} + +int main() +{ + // Ensure we don't kill what was already in the process group. + int status = setpgid(0, 0); + ERROR_IF(setpgid, status, == -1); + + for (unsigned int i = 0; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + kill_group(sig); + } + return EXIT_SUCCESS; +} diff --git a/tests/signals/kill-invalid.c b/tests/signals/kill-invalid.c new file mode 100644 index 0000000000..8cf8e7d3e6 --- /dev/null +++ b/tests/signals/kill-invalid.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +//this test ensures that sending an invalid signal will set errno to esrch + +int main() +{ + + /* + * ESRCH + */ + int status; + status = kill(999999, 0); + ERROR_IF(kill, status, != -1); + ERROR_IF(kill, errno, != ESRCH); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/kill-permission.c b/tests/signals/kill-permission.c new file mode 100644 index 0000000000..eab0aef545 --- /dev/null +++ b/tests/signals/kill-permission.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +// makes sure that a process is not killed if the user doesn't have permission to kill the process + +int main(void) +{ + int status; + // This is added in case user is root. If user is normal user, then it has no effect on the tests + setuid(1000); + status = kill(1, 0); + ERROR_IF(kill, status, != -1); + ERROR_IF(kill, errno, != EPERM); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/kill-self.c b/tests/signals/kill-self.c new file mode 100644 index 0000000000..f05ec12a9f --- /dev/null +++ b/tests/signals/kill-self.c @@ -0,0 +1,56 @@ +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +/* + * Test signal catching when signalling self. + * Ensure all signals can be caught (other than SIGKILL and SIGSTOP). + */ + +volatile sig_atomic_t handler_called = 0; + +void sig_handler(int sig) +{ + (void) sig; + handler_called = 1; +} + +int kill_self(int sig) +{ + struct sigaction act; + int status; + + handler_called = 0; + + act.sa_handler = sig_handler; + act.sa_flags = 0; + + status = sigemptyset(&act.sa_mask); + ERROR_IF(sigemptyset, status, == -1); + + status = sigaction(sig, &act, NULL); + ERROR_IF(sigaction, status, == -1); + + status = kill(getpid(), sig); + ERROR_IF(kill, status, != 0); + + assert(handler_called == 1); + + return EXIT_SUCCESS; +} + +int main() +{ + + for (unsigned int i = 1; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + kill_self(sig); + } + return EXIT_SUCCESS; +} diff --git a/tests/signals/kill0-self.c b/tests/signals/kill0-self.c new file mode 100644 index 0000000000..ad76980233 --- /dev/null +++ b/tests/signals/kill0-self.c @@ -0,0 +1,16 @@ +#include +#include "../test_helpers.h" + +/* + * Send signal 0 to self. This just reports whether a signal can be sent. + */ + +int main() +{ + int status = 0; + + status = kill(getpid(), 0); + ERROR_IF(kill, status, != 0); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/killpg-child.c b/tests/signals/killpg-child.c new file mode 100644 index 0000000000..1291f13959 --- /dev/null +++ b/tests/signals/killpg-child.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// test killing a child process + +void sig_handler (int signo) { + (void) signo; + exit(EXIT_SUCCESS); +} + +int killpg_test2(int signum) +{ + int child_pid, child_pgid; + printf("we are on signal %d\n ", signum); + + if ((child_pid = fork()) == 0) { + /* child here */ + struct sigaction act; + act.sa_handler=sig_handler; + act.sa_flags=0; + sigemptyset(&act.sa_mask); + sigaction(signum, &act, 0); + + /* change child's process group id */ + setpgrp(); + + sigpause(SIGABRT); + + return EXIT_FAILURE; + } else { + /* parent here */ + int i; + sigignore(signum); + + sleep(1); + + child_pgid = getpgid(child_pid); + ERROR_IF(getpgid, child_pgid, == -1); + + int status; + status = killpg(child_pgid, signum); + ERROR_IF(killpg, status, != 0); + + status = wait(&i); + ERROR_IF(wait, status, == -1); + + if (WEXITSTATUS(i) == EXIT_SUCCESS) { + printf("Child exited normally\n"); + printf("Test PASSED\n"); + return EXIT_SUCCESS; + } else { + printf("Child did not exit normally.\n"); + printf("Test FAILED\n"); + exit(EXIT_FAILURE); + } + } + + return EXIT_FAILURE; +} + +int main(){ + int x; + for (unsigned int i = 1; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP || sig == SIGCHLD || sig == SIGINT || sig == SIGQUIT) + { + continue; + } + x = killpg_test2(sig); + if (x == EXIT_FAILURE){ + return EXIT_FAILURE; + } + } + return EXIT_SUCCESS; +} + diff --git a/tests/signals/killpg-esrch.c b/tests/signals/killpg-esrch.c new file mode 100644 index 0000000000..ab1e62cd96 --- /dev/null +++ b/tests/signals/killpg-esrch.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +// if a user tries to kill a process that does not exist the esrch error will be returned +int main() +{ + + int status; + status = killpg(999999, 0); + ERROR_IF(killpg, status, !=-1); + + ERROR_IF(killpg, errno, != ESRCH); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/killpg-invalid.c b/tests/signals/killpg-invalid.c new file mode 100644 index 0000000000..b1f89dc023 --- /dev/null +++ b/tests/signals/killpg-invalid.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +// the test makes sure that if an invalid signal is passed it will return the EINVAL error +int main() +{ + int pgrp; + + pgrp = getpgrp(); + ERROR_IF(getpgrp, pgrp, == -1); + + int status; + status = killpg(pgrp, -1); + ERROR_IF(killpg, status, != -1); + + ERROR_IF(killpg, errno, != EINVAL); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/killpg-self.c b/tests/signals/killpg-self.c new file mode 100644 index 0000000000..afd4865112 --- /dev/null +++ b/tests/signals/killpg-self.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// Test that the killpg() function shall send signal sig to the process +// group specified by prgp. + +void sig_handler(int signo) +{ + // printf("Caught signal %d being tested!\n", signo); + // printf("Test PASSED\n"); + (void) signo; + return; +} + +int killpg_test1(int signum) +{ + int pgrp; + struct sigaction act; + + act.sa_handler=sig_handler; + act.sa_flags=0; + int status = sigemptyset(&act.sa_mask); + ERROR_IF(sigemptyset, status, == -1); + + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + pgrp = getpgrp(); + ERROR_IF(getpgrp, pgrp, == -1); + + status = killpg(pgrp, signum); + ERROR_IF(killpg, status, != 0); + + return EXIT_SUCCESS; +} + +int main(){ + // UB if pg == 1, so set it here first + int status = setpgid(0, 0); + ERROR_IF(setpgid, status, == -1); + + for (unsigned int i = 0; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + killpg_test1(sig); + } + return EXIT_SUCCESS; +} + diff --git a/tests/signals/killpg0-self.c b/tests/signals/killpg0-self.c new file mode 100644 index 0000000000..e319660eca --- /dev/null +++ b/tests/signals/killpg0-self.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include "../test_helpers.h" + +// test sending signal 0 to self will killpg + +int main() +{ + // UB if pg == 1, so set it here first + int err = setpgid(0, 0); + ERROR_IF(setpgid, err, == -1); + + int pgrp; + + pgrp = getpgrp(); + ERROR_IF(getpgrp, pgrp, == -1); + + int status; + status = killpg(pgrp, 0); + ERROR_IF(killpg, status, != 0); + + return EXIT_SUCCESS; +} diff --git a/tests/signals/pthread_kill-child.c b/tests/signals/pthread_kill-child.c new file mode 100644 index 0000000000..842bd68e73 --- /dev/null +++ b/tests/signals/pthread_kill-child.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +//test with pthread_kill to kill a child process + +void * thread_function(void *arg) +{ + /* Does nothing */ + (void) arg; + pthread_exit((void*)0); + + /* To please some compilers */ + return NULL; +} + +int main() +{ + pthread_t child_thread; + pthread_t invalid_tid; + + int rc; + + rc = pthread_create(&child_thread, NULL, + thread_function, NULL); + ERROR_IF(pthread_create, rc, != 0); + + rc = pthread_join(child_thread, NULL); + ERROR_IF(pthread_join, rc, != 0); + + // Now the child_thread exited, it is an invalid tid + memcpy(&invalid_tid, &child_thread, + sizeof(pthread_t)); + sleep(3); + + int status; + status = pthread_kill(invalid_tid, 0); + ERROR_IF(pthread_kill, status, != ESRCH); + + exit(EXIT_SUCCESS); +} \ No newline at end of file diff --git a/tests/signals/pthread_kill-invalid.c b/tests/signals/pthread_kill-invalid.c new file mode 100644 index 0000000000..053f817557 --- /dev/null +++ b/tests/signals/pthread_kill-invalid.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +//test with pthread_kill making sure sending an invalid signal returns einval + +int main() +{ + pthread_t main_thread; + + main_thread = pthread_self(); + + int status; + status = pthread_kill(main_thread, -1); + ERROR_IF(pthread_kill, status, != EINVAL); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/pthread_kill-self.c b/tests/signals/pthread_kill-self.c new file mode 100644 index 0000000000..3e70746141 --- /dev/null +++ b/tests/signals/pthread_kill-self.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +//test pthread_kill on self + +# define INTHREAD 0 +# define INMAIN 1 +# define SIGTOTEST SIGABRT + +int sem1; /* Manual semaphore */ +volatile sig_atomic_t handler_called = 0; +int count = 1; + +struct signal { + int signum; +}; + +void handler() { + handler_called = 1; + return; +} + +void *a_thread_func( void *arg) +{ + + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + sigaction(((struct signal *)arg)->signum, &act, 0); + + sem1=INMAIN; + + while(sem1==INMAIN) + sleep(1); + + // sleep(50); + + handler_called=-1; + pthread_exit(0); + return NULL; +} + +int pthread_kill_test1(int signum) +{ + pthread_t new_th; + + sem1=INTHREAD; + + struct signal arg; + arg.signum = signum; + + int status; + status = pthread_create(&new_th, NULL, a_thread_func, &arg); + ERROR_IF(pthread_create, status, != 0); + + while(sem1==INTHREAD) + sleep(1); + + status = pthread_kill(new_th, signum); + ERROR_IF(pthread_kill, status, != 0); + + sleep(2); + sem1=INTHREAD; + + while(handler_called==0) + sleep(1); + + ERROR_IF(pthread_kill, handler_called, == -1); + ERROR_IF(pthread_kill, handler_called, == 0); + + handler_called = 0; + return EXIT_SUCCESS; +} + +int main(){ + for (unsigned int i = 0; i < sizeof(signals_list)/sizeof(signals_list[0]); i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + pthread_kill_test1(sig); + } + return EXIT_SUCCESS; +} + diff --git a/tests/signals/pthread_kill0-self.c b/tests/signals/pthread_kill0-self.c new file mode 100644 index 0000000000..a4723a9e94 --- /dev/null +++ b/tests/signals/pthread_kill0-self.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +// test sending 0 with pthread_kill to self + +int main() +{ + pthread_t main_thread; + + main_thread = pthread_self(); + + int status; + status = pthread_kill(main_thread, 0); + ERROR_IF(pthread_kill, status, != 0); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/raise-compliance.c b/tests/signals/raise-compliance.c new file mode 100644 index 0000000000..6722729398 --- /dev/null +++ b/tests/signals/raise-compliance.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// The raise() function shall send the signal sig to the executing [CX] [Option Start] thread or process. [Option End] If a signal handler is called, the raise() function shall not return until after the signal handler does. + +// [CX] [Option Start] The effect of the raise() function shall be equivalent to calling: pthread_kill(pthread_self(), sig); + +void sig_hand(int i) + +{ + if (i < 1 || i > 32){ + printf("an invalid signal was given: %d", i); + } + static int count = 1; + + count++; + printf("%d \n", count); + if (count == 32) { + printf("reached 32nd signal\n"); + return; + } + else{ + printf("count is %d\n", count); + } +} + +void raise_test(int sig){ + signal(sig, sig_hand); + raise(sig); +} + +int main(void) +{ + for (int i = 0; i < N_SIGNALS; i++) + { + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP) + { + continue; + } + raise_test(sig); + } + return EXIT_SUCCESS; +} + diff --git a/tests/signals/sigaddset-add.c b/tests/signals/sigaddset-add.c new file mode 100644 index 0000000000..556d7781c6 --- /dev/null +++ b/tests/signals/sigaddset-add.c @@ -0,0 +1,39 @@ + +#define _OPEN_SYS +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + + // The sigaddset() function adds the individual signal specified by the signo to the signal set pointed to by set. + + // Applications shall call either sigemptyset() or sigfillset() at least once for each object of type sigset_t prior to any other use of that object. If such an object is not initialized in this way, but is nonetheless supplied as an argument to any of pthread_sigmask(), sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(), sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or sigwaitinfo(), the results are undefined. + +void addset_test(sigset_t *sigset, int signal){ + int status; + + status = sigismember(sigset, signal); + ERROR_IF(sigismember, status, != 0); + + status = sigaddset(sigset, signal); + ERROR_IF(sigaddset, status, != 0); + + status = sigismember(sigset, signal); + ERROR_IF(sigismember, status, != 1); + +} + +int main() { + sigset_t sigset; + + sigemptyset(&sigset); + +for (int i = 1; i < N_SIGNALS; i++){ + int sig = signals_list[i-1].signal; + + addset_test(&sigset, sig); + } + + +} diff --git a/tests/signals/sigdelset-delete.c b/tests/signals/sigdelset-delete.c new file mode 100644 index 0000000000..224d74a301 --- /dev/null +++ b/tests/signals/sigdelset-delete.c @@ -0,0 +1,36 @@ +#define _OPEN_SYS +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// The sigdelset() function deletes the individual signal specified by signo from the signal set pointed to by set. + +// Applications should call either sigemptyset() or sigfillset() at least once for each object of type sigset_t prior to any other use of that object. If such an object is not initialized in this way, but is nonetheless supplied as an argument to any of pthread_sigmask(), sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(), sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or sigwaitinfo(), the results are undefined. + + +void delset_test(sigset_t *sigset, int signal){ + int status; + status = sigismember(sigset, signal); + ERROR_IF(sigismember, status, != 1); + + status = sigdelset(sigset, signal); + ERROR_IF(sigdelset, status, != 0); + + status = sigismember(sigset, signal); + ERROR_IF(sigismember, status, != 0); + +} + +int main() { + sigset_t sigset; + + sigfillset(&sigset); + + for (int i = 1; i < N_SIGNALS; i++){ + int sig = signals_list[i-1].signal; + delset_test(&sigset, sig); + } + +} diff --git a/tests/signals/sigismember-invalid.c b/tests/signals/sigismember-invalid.c new file mode 100644 index 0000000000..80c45fa236 --- /dev/null +++ b/tests/signals/sigismember-invalid.c @@ -0,0 +1,21 @@ +#define _OPEN_SYS +#include +#include +#include +#include +#include "../test_helpers.h" + +// test to make sure that if you pass an invalid signal to sigismember it will return EINVAL + +int main() { + sigset_t sigset; + int status; + + sigfillset(&sigset); + status = sigismember(&sigset, -1); + ERROR_IF(sigismember, status, != -1); + ERROR_IF(sigismember, errno, != EINVAL); + + return EXIT_SUCCESS; + +} \ No newline at end of file diff --git a/tests/signals/sigismember-valid.c b/tests/signals/sigismember-valid.c new file mode 100644 index 0000000000..e6c54f5894 --- /dev/null +++ b/tests/signals/sigismember-valid.c @@ -0,0 +1,42 @@ +#define _OPEN_SYS +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// The sigismember() function shall test whether the signal specified by signo is a member of the set pointed to by set. + +// Applications should call either sigemptyset() or sigfillset() at least once for each object of type sigset_t prior to any other use of that object. If such an object is not initialized in this way, but is nonetheless supplied as an argument to any of pthread_sigmask(), sigaction(), sigaddset(), sigdelset(), sigismember(), sigpending(), sigprocmask(), sigsuspend(), sigtimedwait(), sigwait(), or sigwaitinfo(), the results are undefined. + +void check_full(sigset_t set, int signum) { + if (!sigismember(&set, signum)) { + exit(EXIT_FAILURE); + } + +} + +void check_empty(sigset_t set, int signum) { + if (sigismember(&set, signum)) { + exit(EXIT_FAILURE); + } + +} + + + +int main() { + sigset_t sigset; + + sigfillset(&sigset); + for (int i=1; i + +/* + * This is a test to ensure all required items for signal.h are defined. + * The definitions follow the order described in + * + */ + +void handler(int sig_num) +{ + (void)sig_num; +} + +void action(int sig_num, siginfo_t *info, void *context) +{ + (void)sig_num; + (void)info; + (void)context; +} + +int main() +{ + int (*sh)(int) __attribute__((unused)) = sighold; + int (*sigig)(int) __attribute__((unused)) = sigignore; + int (*sigintr)(int, int) __attribute__((unused)) = siginterrupt; + int (*paws)(int) __attribute__((unused)) = sigpause; + int (*srls)(int) __attribute__((unused)) = sigrelse; + void (*(*sset)(int, void (*)(int)))(int) __attribute__((unused)) = sigset; + + return EXIT_SUCCESS; +} diff --git a/tests/signals/signal-h.c b/tests/signals/signal-h.c new file mode 100644 index 0000000000..8ec09b374d --- /dev/null +++ b/tests/signals/signal-h.c @@ -0,0 +1,232 @@ +#include "../test_helpers.h" +#include + +/* + * This is a test to ensure all required items for signal.h are defined. + * The definitions follow the order described in + * + */ + +void handler(int sig_num) +{ + (void)sig_num; +} + +void action(int sig_num, siginfo_t *info, void *context) +{ + (void)sig_num; + (void)info; + (void)context; +} + +int main() +{ + void (*sig_dfl)(int) __attribute__((unused)) = SIG_DFL; + void (*sig_err)(int) __attribute__((unused)) = SIG_ERR; + void (*sig_ign)(int) __attribute__((unused)) = SIG_IGN; + + pthread_t pthread_num __attribute__((unused)) = 0; + size_t size __attribute__((unused)) = 0; + uid_t uid __attribute__((unused)) = 0; + + sig_atomic_t atomic __attribute__((unused)) = 0; + sigset_t sig_set __attribute__((unused)) ; + pid_t pid __attribute__((unused)) = 0; + + pthread_attr_t *attr __attribute__((unused)) = NULL; + + // struct sigevent sev; + union sigval sv; + + sv.sival_int = (int)0; + sv.sival_ptr = (void *)0; + + // sev.sigev_notify = (int)0; + // sev.sigev_notify = SIGEV_NONE; + // sev.sigev_notify = SIGEV_SIGNAL; + // sev.sigev_notify = SIGEV_THREAD; + + // sev.sigev_signo = (int)0; + // sev.sigev_value = sv; + // sev.sigev_value.sival_int = (int)0; + // sev.sigev_value.sival_ptr = (void *)0; + // sev.sigev_notify_function = (void (*)(union sigval))0; + // sev.sigev_notify_attributes = (pthread_attr_t *)0; + + int rt_sig_num __attribute__((unused)) = SIGRTMIN; + rt_sig_num = SIGRTMAX; + + // rt_sig_num = SIG2STR_MAX; + + // sev.sigev_signo = SIGABRT; + // sev.sigev_signo = SIGALRM; + // sev.sigev_signo = SIGBUS; + // sev.sigev_signo = SIGCHLD; + // sev.sigev_signo = SIGCONT; + // sev.sigev_signo = SIGFPE; + // sev.sigev_signo = SIGHUP; + // sev.sigev_signo = SIGILL; + // sev.sigev_signo = SIGINT; + // sev.sigev_signo = SIGKILL; + // sev.sigev_signo = SIGPIPE; + // sev.sigev_signo = SIGQUIT; + // sev.sigev_signo = SIGSEGV; + // sev.sigev_signo = SIGSTOP; + // sev.sigev_signo = SIGTERM; + // sev.sigev_signo = SIGTSTP; + // sev.sigev_signo = SIGTTIN; + // sev.sigev_signo = SIGTTOU; + // sev.sigev_signo = SIGUSR1; + // sev.sigev_signo = SIGUSR2; + // sev.sigev_signo = SIGWINCH; + // sev.sigev_signo = SIGPOLL; + // sev.sigev_signo = SIGPROF; + // sev.sigev_signo = SIGSYS; + // sev.sigev_signo = SIGTRAP; + // sev.sigev_signo = SIGURG; + // sev.sigev_signo = SIGVTALRM; + // sev.sigev_signo = SIGXCPU; + // sev.sigev_signo = SIGXFSZ; + + struct sigaction sa; + + sa.sa_handler = SIG_IGN; + sa.sa_handler = SIG_DFL; + sa.sa_handler = handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = (int)0; + sa.sa_sigaction = action; + +#ifndef SA_NOCLDSTOP +#error "Required constant not defined SA_NOCLDSTOP" +#endif +#ifndef SIG_BLOCK +#error "Required constant not defined SIG_BLOCK" +#endif +#ifndef SIG_UNBLOCK +#error "Required constant not defined SIG_UNBLOCK" +#endif +#ifndef SIG_SETMASK +#error "Required constant not defined SIG_SETMASK" +#endif +#ifndef SA_ONSTACK +#error "Required constant not defined SA_ONSTACK" +#endif +#ifndef SA_RESETHAND +#error "Required constant not defined SA_RESETHAND" +#endif +#ifndef SA_RESTART +#error "Required constant not defined SA_RESTART" +#endif +#ifndef SA_SIGINFO +#error "Required constant not defined SA_SIGINFO" +#endif +#ifndef SA_NOCLDWAIT +#error "Required constant not defined SA_NOCLDWAIT" +#endif +#ifndef SA_NODEFER +#error "Required constant not defined SA_NODEFER" +#endif +#ifndef SS_ONSTACK +#error "Required constant not defined SS_ONSTACK" +#endif +#ifndef SS_DISABLE +#error "Required constant not defined SS_DISABLE" +#endif +#ifndef MINSIGSTKSZ +#error "Required constant not defined MINSIGSTKSZ" +#endif +#ifndef SIGSTKSZ +#error "Required constant not defined SIGSTKSZ" +#endif + + // struct ucontext_t uc; + mcontext_t mc __attribute__((unused)); + + // add parts to ucontext_t + // uc.uc_link = NULL; + // uc.uc_sigmask = 0; + // uc.uc_stack = NULL; + // uc.uc_mcontext = NULL; + + + stack_t st __attribute__((unused)); + st.ss_sp = NULL; + st.ss_size = (size_t)0; + st.ss_flags = (int)0; + + siginfo_t si __attribute__((unused)); + si.si_signo = SIGHUP; + si.si_code = (int)0; + si.si_errno = (int)0; + si.si_pid = (pid_t)0; + si.si_uid = (uid_t)0; + si.si_addr = NULL; + si.si_status = (int)0; + si.si_value = sv; + + // si.si_code = ILL_ILLOPC; + // si.si_code = ILL_ILLOPN; + // si.si_code = ILL_ILLADR; + // si.si_code = ILL_ILLTRP; + // si.si_code = ILL_PRVOPC; + // si.si_code = ILL_PRVREG; + // si.si_code = ILL_COPROC; + // si.si_code = ILL_BADSTK; + // si.si_code = FPE_INTDIV; + // si.si_code = FPE_INTOVF; + // si.si_code = FPE_FLTDIV; + // si.si_code = FPE_FLTOVF; + // si.si_code = FPE_FLTUND; + // si.si_code = FPE_FLTRES; + // si.si_code = FPE_FLTINV; + // si.si_code = FPE_FLTSUB; + // si.si_code = SEGV_MAPERR; + // si.si_code = SEGV_ACCERR; + // si.si_code = BUS_ADRALN; + // si.si_code = BUS_ADRERR; + // si.si_code = BUS_OBJERR; + // si.si_code = TRAP_BRKPT; + // si.si_code = TRAP_TRACE; + // si.si_code = CLD_EXITED; + // si.si_code = CLD_KILLED; + // si.si_code = CLD_DUMPED; + // si.si_code = CLD_TRAPPED; + // si.si_code = CLD_STOPPED; + // si.si_code = CLD_CONTINUED; + // si.si_code = SI_USER; + // si.si_code = SI_QUEUE; + // si.si_code = SI_TIMER; + // si.si_code = SI_ASYNCIO; + // si.si_code = SI_MESGQ; + + // void (*(*bs)(int, void (*)(int)))(int) = bsd_signal; + int (*k)(pid_t, int) __attribute__((unused))= kill; + int (*kpg)(pid_t, int) __attribute__((unused))= killpg; + void (*psig)(const siginfo_t *, const char *) __attribute__((unused))= psiginfo; + void (*ps)(int, const char *) __attribute__((unused))= psignal; + int (*ptk)(pthread_t, int) __attribute__((unused))= pthread_kill; + int (*ptsm)(int, const sigset_t *, sigset_t *) __attribute__((unused))= pthread_sigmask; + int (*r)(int) __attribute__((unused))= raise; + // int (*s2s)(int, char*) = sig2str; + int (*sact)(int, const struct sigaction *restrict, + struct sigaction *restrict) __attribute__((unused)) = sigaction; + int (*sas)(sigset_t *, int) __attribute__((unused))= sigaddset; + int (*sastk)(const stack_t *restrict, stack_t *restrict) __attribute__((unused))= sigaltstack; + int (*sds)(sigset_t *, int) __attribute__((unused))= sigdelset; + int (*ses)(sigset_t *) __attribute__((unused))= sigemptyset; + int (*sfs)(sigset_t *) __attribute__((unused))= sigfillset; + int (*ismem)(const sigset_t *, int) __attribute__((unused))= sigismember; + void ( *(*sgnl)(int, void (*)(int)))(int) __attribute__((unused))= signal; + int (*pend)(sigset_t *) __attribute__((unused))= sigpending; + int (*spmsk)(int, const sigset_t *restrict, sigset_t *restrict) __attribute__((unused))= sigprocmask; + int (*sigq)(pid_t, int, const union sigval) __attribute__((unused))= sigqueue; + int (*susp)(const sigset_t *) __attribute__((unused))= sigsuspend; + int (*stmwt)(const sigset_t *restrict, siginfo_t *restrict, + const struct timespec *restrict) __attribute__((unused))= sigtimedwait; + int (*swt)(const sigset_t *restrict, int *restrict) __attribute__((unused))= sigwait; + int (*swtinfo)(const sigset_t *restrict, siginfo_t *restrict) __attribute__((unused))= sigwaitinfo; + // int (*str2s)(const char *restrict, int *restrict) = str2sig; + + return EXIT_SUCCESS; +} diff --git a/tests/signals/signal-handle_return.c b/tests/signals/signal-handle_return.c new file mode 100644 index 0000000000..933f992078 --- /dev/null +++ b/tests/signals/signal-handle_return.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "../test_helpers.h" + +void SIGUSR1_handler(int signo) +{ + (void) signo; + printf("do nothing useful\n"); +} + +void SIGUSR2_handler(int signo) +{ + (void) signo; + printf("do nothing useful\n"); +} + +int main() +{ + void (*status) (int); + status = signal(SIGUSR1, SIGUSR1_handler); + ERROR_IF(signal, status, == SIG_ERR); + + status = signal(SIGUSR2, SIGUSR2_handler); + ERROR_IF(signal, status, == SIG_ERR); + + status = signal(SIGUSR1,SIG_IGN); + // printf("status is %d\n", status); + // printf("SIGUSR1_handler is %d\n", SIGUSR1_handler); + ERROR_IF(signal, status, != SIGUSR1_handler); + + //this seems to be a weird comparison error + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/signal-handler.c b/tests/signals/signal-handler.c new file mode 100644 index 0000000000..f6eba8e168 --- /dev/null +++ b/tests/signals/signal-handler.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + printf("SIGCHLD called. Inside handler\n"); + handler_called = 1; +} + +int main() +{ + void (*status) (int); + status = signal(SIGCHLD, sig_handler); + ERROR_IF(signal, status, == SIG_ERR); + + status = signal(SIGCHLD,SIG_DFL); + ERROR_IF(signal, status, != sig_handler); + + //same comparison error from handle_return + + raise(SIGCHLD); + + if (handler_called == 1) { + return EXIT_FAILURE; + } + handler_called = 0; + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/signal-handler2.c b/tests/signals/signal-handler2.c new file mode 100644 index 0000000000..7cc8394bdd --- /dev/null +++ b/tests/signals/signal-handler2.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + // printf("%d called. Inside handler\n", signo); + handler_called = 1; +} + +int signal_test3(int signum) +{ + void (*status) (int); + status = signal(signum, sig_handler); + ERROR_IF(signal, status, == SIG_ERR); + + raise(signum); + + ERROR_IF(raise, handler_called, != 1); + return EXIT_SUCCESS; +} + +int main(){ + for (unsigned int i = 0; i < sizeof(signals_list)/sizeof(signals_list[0]); i++){ + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP){ + continue; + } + signal_test3(sig); + } + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/signal-ignore.c b/tests/signals/signal-ignore.c new file mode 100644 index 0000000000..37a7c744bf --- /dev/null +++ b/tests/signals/signal-ignore.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + printf("%d called. Inside handler\n", signo); + handler_called = 1; +} + +int signal_test2(int signum) +{ + void (*status) (int); + status = signal(signum, sig_handler); + ERROR_IF(signal, status, == SIG_ERR); + + status = signal(signum, SIG_IGN); + ERROR_IF(signal, status, != sig_handler); + + // same issue as handle_return + + raise(signum); + + ERROR_IF(raise, handler_called, == 1); + handler_called = 0; + return EXIT_SUCCESS; +} + +int main(){ + for (unsigned int i = 0; i < sizeof(signals_list)/sizeof(signals_list[0]); i++){ + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP){ + continue; + } + signal_test2(sig); + } + return EXIT_SUCCESS; +} + + + diff --git a/tests/signals/signal-invalid.c b/tests/signals/signal-invalid.c new file mode 100644 index 0000000000..afad26247a --- /dev/null +++ b/tests/signals/signal-invalid.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include "../test_helpers.h" + +// test to make sure sending an invalid signal sets errno + +void sig_handler(int signo) +{ + (void) signo; + printf("handler does nothing useful.\n"); +} + +int main() +{ + errno = -1; + + void (*status) (int); + status = signal(-1, sig_handler); + ERROR_IF(signal, status, != SIG_ERR); + ERROR_IF(signal, errno, <= 0); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/signal-uncatchable.c b/tests/signals/signal-uncatchable.c new file mode 100644 index 0000000000..1bf85db82c --- /dev/null +++ b/tests/signals/signal-uncatchable.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include "../test_helpers.h" + +//make sure you can't catch uncatchable signals + +void sig_handler(int signo) +{ + (void) signo; + printf("handler does nothing useful.\n"); +} + +int main() +{ + errno = -1; + void (*status) (int); + status = signal(SIGKILL, sig_handler); + ERROR_IF(signal, status, != SIG_ERR); + + ERROR_IF(signal, errno, <= 0); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/signals_list.h b/tests/signals/signals_list.h new file mode 100644 index 0000000000..75bf3cd847 --- /dev/null +++ b/tests/signals/signals_list.h @@ -0,0 +1,79 @@ +#ifndef _SIGNALS_LIST +#define _SIGNALS_LIST 1 + +#include + +#ifdef SIGSTKFLT +#endif + +const int N_SIGNALS = (28 +#ifdef SIGSTKFLT + + 1 +#endif +#ifdef SIGWINCH + + 1 +#endif +#ifdef SIGIO + + 1 +#endif +#ifdef SIGPWR + + 1 +#endif +#ifdef SIGUNUSED + + 1 +#endif +); + +struct signalAction +{ + int signal; + char action; +}; + +const struct signalAction signals_list[] = { + {SIGABRT, 'A'}, + {SIGALRM, 'T'}, + {SIGBUS, 'A'}, + {SIGCHLD, 'I'}, + {SIGCONT, 'C'}, + {SIGFPE, 'A'}, + {SIGHUP, 'T'}, + {SIGILL, 'A'}, + {SIGINT, 'T'}, + {SIGKILL, 'T'}, + {SIGPIPE, 'T'}, + {SIGQUIT, 'A'}, + {SIGSEGV, 'A'}, + {SIGSTOP, 'S'}, + {SIGTERM, 'T'}, + {SIGTSTP, 'S'}, + {SIGTTIN, 'S'}, + {SIGTTOU, 'S'}, + {SIGUSR1, 'T'}, + {SIGUSR2, 'T'}, + // {SIGPOLL, 'T'}, + {SIGPROF, 'T'}, + {SIGSYS, 'A'}, + {SIGTRAP, 'A'}, + {SIGURG, 'I'}, + {SIGVTALRM, 'T'}, + {SIGXCPU, 'A'}, + {SIGXFSZ, 'A'}, +#ifdef SIGSTKFLT + {SIGSTKFLT, 'T'}, +#endif +#ifdef SIGWINCH + {SIGWINCH, 'I'}, +#endif +#ifdef SIGIO + {SIGIO, 'T'}, +#endif +#ifdef SIGPWR + {SIGPWR, 'T'}, +#endif +#ifdef SIGUNUSED + {SIGUNUSED, 'A'}, +#endif +}; + +#endif /* _SIGNALS_LIST */ diff --git a/tests/signals/sigpause-error.c b/tests/signals/sigpause-error.c new file mode 100644 index 0000000000..c770a1e9da --- /dev/null +++ b/tests/signals/sigpause-error.c @@ -0,0 +1,103 @@ +#define _XOPEN_SOURCE 700 + +#include +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// This program verifies that sigpause() returns -1 and sets errno to EINTR +// when it returns. + +#define INMAIN 0 +#define INTHREAD 1 + +int handler_called = 0; +int returned = 0; +int return_value = 2; +int result = 2; +int sem = INMAIN; + +void handler() { + // printf("signal was called\n"); + handler_called = 1; + return; +} + +void *d_thread_func(void *sig) +{ + + int signum = *(int *)sig; + printf("%d Pausing signal \n", signum); + int return_value = 0; + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + sigaction(signum, &act, 0); + return_value = sigpause(signum); + ERROR_IF(sigpause, return_value, != -1); + ERROR_IF(sigpause, errno, != EINTR); + result = 0; + if (return_value == -1) { + if (errno == EINTR) { + printf ("Test PASSED: sigpause returned -1 and set errno to EINTR\n"); + result = 0; + } else { + printf ("Test FAILED: sigpause did not set errno to EINTR\n"); + result = 1; + } + } else { + if (errno == EINTR) { + printf ("Test FAILED: sigpause did not return -1\n"); + } + printf ("Test FAILED: sigpause did not set errno to EINTR\n"); + printf ("Test FAILED: sigpause did not return -1\n"); + result = 1; + + } + sem = INMAIN; + return NULL; +} + + +int sigpause_error(int signum){ + pthread_t new_th; + + int status; + status = pthread_create(&new_th, NULL, d_thread_func, (void *)&signum); + ERROR_IF(pthread_create, status, != 0); + + sleep(1); + + status = pthread_kill(new_th, signum); + ERROR_IF(pthread_kill, status, != 0); + + sem = INTHREAD; + while (sem == INTHREAD) + sleep(1); + + if(result == 2) { + exit(EXIT_FAILURE); + } + if(result == 1) { + exit(EXIT_FAILURE); + } + + printf("Test PASSED\n"); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include +#include +#include +#include + +// This program verifies that sigpause() returns -1 and sets errno to EINVAL +// if passed an invalid signal number. + +#define INMAIN 0 +#define INTHREAD 1 + +volatile sig_atomic_t handler_called = 0; +int returned = 0; +int return_value = 2; +int result = 2; +int sem = INMAIN; + +void handler() { + // printf("signal was called\n"); + handler_called = 1; + return; +} + +int sigpause_invalid(){ + int return_value = 0; + + return_value = sigpause(-1); + + if (return_value == -1) { + if (errno == EINVAL) { + printf ("Test PASSED: sigpause returned -1 and set errno to EINVAL\n"); + return EXIT_SUCCESS; + } else { + printf ("Test FAILED: sigpause did not set errno to EINVAL\n"); + exit(EXIT_FAILURE); + } + } else { + printf ("Test FAILED: sigpause did not return -1\n"); + if (errno == EINVAL) { + printf ("Test FAILED: sigpause did not set errno to EINVAL\n"); + } + exit(EXIT_FAILURE); + } + return EXIT_SUCCESS; + +} + +int main(){ + sigpause_invalid(); + return EXIT_SUCCESS; +} + diff --git a/tests/signals/sigpause-pause.c b/tests/signals/sigpause-pause.c new file mode 100644 index 0000000000..4caf0e62c8 --- /dev/null +++ b/tests/signals/sigpause-pause.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// This program verifies that sigpause() removes sig from the signal mask. + +int handler_called = 0; + +void handler() { + handler_called = 1; + return; +} + +void *a_thread_func(void *sig) +{ + int status; + int signum = *(int *)sig; + printf("Pausing signal %s\n", signum); + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = handler; + status = sigemptyset(&act.sa_mask); + ERROR_IF(sigemptyset, status, != 0); + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, != 0); + status = sighold(signum); + ERROR_IF(sighold, status, != 0); + status = sigpause(signum); + ERROR_IF(sigpause, status, != 0); + + return NULL; +} + + + +int sigpause_basic(int signum) +{ + pthread_t new_th; + int status; + status = pthread_create(&new_th, NULL, a_thread_func, (void *)&signum); + ERROR_IF(pthread_create, status, != 0); + + sleep(1); + + status = pthread_kill(new_th, signum); + ERROR_IF(pthread_kill, status, != 0); + + sleep(1); + + if (handler_called != 1){ + prinft("handler wasn't called\n"); + exit(EXIT_FAILURE); + } + handler_called = 0; + + return EXIT_SUCCESS; +} + + + +int main(){ + for (int i=1; i +#include +#include +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// This program verifies that sigpause() restores sig to the signal mask before +// returning. + +volatile sig_atomic_t handler_called = false; + +void handler() { + handler_called = true; + return; +} + +void *c_thread_func(void *sig) +{ + int signum = *(int *)sig; + printf("%d !!!\n", signum); + + sigset_t pendingset; + + puts("before sigpause"); + + assert(!handler_called); + + if ((sigpause(signum) != -1) || (errno != EINTR)) { + puts("Test UNRESOLVED: sigpause didn't return -1 and/or didn't set errno correctly."); + exit(2); + return NULL; + } + assert(handler_called); + handler_called = false; + + int status = raise(signum); + ERROR_IF(raise, status, == -1); + + assert(!handler_called); + + sigpending(&pendingset); + if (sigismember(&pendingset, signum) == 1) { + puts("Test PASSED: signal mask was restored when sigpause returned."); + } + + return NULL; + +} + +int sigpause_revert(int signum) { + pthread_t new_th; + int status; + struct sigaction act; + + // Ensure thread inherits mask with signum blocked. + status = sighold(signum); + ERROR_IF(sighold, status, == -1); + + act.sa_flags = 0; + act.sa_handler = handler; + status = sigemptyset(&act.sa_mask); + ERROR_IF(sigemptyset, status, == -1); + status = sigaction(signum, &act, NULL); + ERROR_IF(sigaction, status, == -1); + + if((status = pthread_create(&new_th, NULL, c_thread_func, (void *)&signum)) != 0) + { + errno = status; + perror("Error creating thread"); + exit(EXIT_FAILURE); + } + + sleep(1); + + if((status = pthread_kill(new_th, signum)) != 0) + { + errno = status; + perror("Test UNRESOLVED: Couldn't send signal to thread"); + exit(EXIT_FAILURE); + } + if ((status = pthread_join(new_th, NULL)) != 0) { + errno = status; + perror("failed to join thread"); + return EXIT_FAILURE; + } + + puts("Test PASSED"); + return EXIT_SUCCESS; +} + + + +int main(){ + for (int i=1; i +#include +#include +#include +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// This program verifies that sigpause() suspends the calling process +// until it receives a signal. + +#define INMAIN 0 +#define INTHREAD 1 + +volatile sig_atomic_t handler_called = 0; +volatile atomic_bool completed = false; + +void handler() { + handler_called = 1; + return; +} +void *b_thread_func(void *code_raw) { + int *code = code_raw; + printf("Pausing signal %s\n", strsignal(*code)); + sigpause(*code); + assert(handler_called != 0); + *code = 0; + atomic_store(&completed, true); + + return NULL; +} + + +int sigpause_suspend(int signum) +{ + atomic_store(&completed, false); + int status; + + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = handler; + sigemptyset(&act.sa_mask); + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + pthread_t new_th; + + int code = signum; + if ((status = pthread_create(&new_th, NULL, b_thread_func, (void *)&code)) != 0) { + errno = status; + perror("failed to create thread"); + return EXIT_FAILURE; + } + sleep(1); + assert(!atomic_load(&completed)); + + if ((status = pthread_kill(new_th, signum)) != 0) { + errno = status; + perror("failed to kill thread"); + return EXIT_FAILURE; + } + + if ((status = pthread_join(new_th, NULL)) != 0) { + errno = status; + perror("failed to join thread"); + return EXIT_FAILURE; + } + + assert(code == 0); + assert(atomic_load(&completed)); + + return EXIT_SUCCESS; +} + + +int main(){ + // TODO: upper limit for i (gives OOB otherwise) + for (int i=1; i<31; i++){ + int sig = signals_list[i].signal; + if (sig == SIGKILL || sig == SIGSTOP){ + continue; + } + printf("For signal %s (%d)\n", strsignal(sig), sig); + sigpause_suspend(sig); + } + return EXIT_SUCCESS; +} + + + diff --git a/tests/signals/sigprocmask-10.c b/tests/signals/sigprocmask-10.c new file mode 100644 index 0000000000..f14c593bdf --- /dev/null +++ b/tests/signals/sigprocmask-10.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include "../test_helpers.h" + +// The thread's signal mask shall not be changed, if sigprocmask( ) fails. + +#define NUMSIGNALS 24 + +int is_changed(sigset_t set) { + + int i; + int siglist[] = {SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + for (i=0; i +#include +#include +#include "../test_helpers.h" + +// sigprocmask( ) shall return 0, Upon successful completion; otherwise, it shall return -1 +// and errno shall be set to indicate the error, and the process' signal mask shall be unchanged. + +int main() +{ + + sigset_t set; + sigaddset (&set, SIGABRT); + + int status; + status = sigprocmask(SIG_SETMASK, &set, NULL); + ERROR_IF(sigprocmask, status, != 0); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/sigprocmask-12.c b/tests/signals/sigprocmask-12.c new file mode 100644 index 0000000000..fe01df4aa4 --- /dev/null +++ b/tests/signals/sigprocmask-12.c @@ -0,0 +1,63 @@ +#define _XOPEN_SOURCE 600 + +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +// An errno value of [EINVAL] shall be returned and the sigprocmask() function shall fail, if the value of +// the how argument is not equal to one of the defined values. + +int main(int argc, char *argv[]) +{ + int signo; + (void) signo; + int r=rand(); + sigset_t set; + + if (argc < 2) { + printf("Usage: %s [1|2|3|4]\n", argv[0]); + exit(EXIT_FAILURE); + } + + /* + Various error conditions + */ + switch (argv[1][0]) { + case '1': + signo=-1; + break; + case '2': + signo=-10000; + break; + case '3': + signo=INT32_MIN+1; + break; + case '4': + signo=INT32_MIN; + break; + default: + printf("Usage: %s [1|2|3|4]\n", argv[0]); + exit(EXIT_FAILURE); + } + + sigaddset(&set, SIGABRT); + + int status; + status = sigprocmask(r, &set, NULL); + ERROR_IF(sigprocmask, status, != -1); + ERROR_IF(sigprocmask, errno, != EINVAL); + // if (sigprocmask(r, &set, NULL) == -1) { + // if (EINVAL == errno) { + // printf ("errno set to EINVAL\n"); + // return EXIT_SUCCESS; + // } else { + // printf ("errno not set to EINVAL\n"); + // exit(EXIT_FAILURE); + // } + // } + + exit(EXIT_FAILURE); +} \ No newline at end of file diff --git a/tests/signals/sigprocmask-3.c b/tests/signals/sigprocmask-3.c new file mode 100644 index 0000000000..aee43032ca --- /dev/null +++ b/tests/signals/sigprocmask-3.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +// The resulting set shall be the union of the current set and the signal +// set pointed to by set, if the value of the argument how is SIG_BLOCK. + +volatile sig_atomic_t handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; +} + +int sigprocmask_block(int signum) +{ + int defaultsig = SIGALRM; + if (signum == SIGALRM) { + defaultsig = SIGHUP; + } + struct sigaction act; + sigset_t set1, set2, pending_set; + sigemptyset(&set1); + sigemptyset(&set2); + sigaddset(&set1, defaultsig); + sigaddset(&set2, signum); + + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + int status; + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigaction(defaultsig, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigprocmask(SIG_SETMASK, &set1, NULL); + ERROR_IF(sigprocmask, status, == -1); + + status = sigprocmask(SIG_UNBLOCK, &set2, NULL); + ERROR_IF(sigprocmask, status, == -1); + + printf("Raising %s\n", strsignal(signum)); + status = raise(signum); + ERROR_IF(raise, status, == -1); + + ERROR_IF(raise, handler_called, != 1); + handler_called = 0; + + printf("Raising %s\n", strsignal(defaultsig)); + status = raise(defaultsig); + ERROR_IF(raise, defaultsig, == -1); + + ERROR_IF(raise, handler_called, == 1); + + status = sigpending(&pending_set); + ERROR_IF(sigpending, status, == -1); + + status = sigismember(&pending_set, defaultsig); + ERROR_IF(sigismember, status, != 1); + + status = sigismember(&pending_set, signum); + ERROR_IF(sigismemeber, status, != 0); + + // printf("Test PASSED: signal was added to the process's signal mask\n"); + act.sa_handler = SIG_IGN; + sigaction(signum, &act, 0); + sigaction(defaultsig, &act, 0); + + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include + +// The previous mask shall be stored in the location pointed to by oset, if the argument oset is not a null pointer. + + +#define NUMSIGNALS 26 + +int main() +{ + sigset_t oactl, tempset; + int i, j, test_failed=0; + + int siglist[] = {SIGABRT, SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + for (i=0; i 0) { + for (j=0; j +#include +#include + +// The value of the argument how is not significant and the process's signal mask shall be unchanged, and +// thus the call can be used to enquire about currently blocked signals, if the argument set is a null +// pointer. + +#define NUMSIGNALS 25 + +int is_changed(sigset_t set, int sig) { + + int i; + int siglist[] = {SIGABRT, SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + if (sigismember(&set, sig) != 1) { + return 1; + } + for (i=0; i +#include +#include + + +#define NUMSIGNALS 25 + +int is_changed(sigset_t set, int sig) { + + int i; + int siglist[] = {SIGABRT, SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + if (sigismember(&set, sig) != 1) { + return 1; + } + for (i=0; i +#include +#include + +#define NUMSIGNALS 25 + +int is_changed(sigset_t set, int sig) { + + int i; + int siglist[] = {SIGABRT, SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + if (sigismember(&set, sig) != 1) { + return 1; + } + for (i=0; i +#include +#include +#include "../test_helpers.h" + +// After the call to sigprocmask(), if there are any pending unblocked signals, at least one of those +// signals shall be delivered before the call to sigprocmask() returns. + +int handler_called = 0; +int sigprocmask_return_val = 1; /* some value that's not a 1 or 0 */ + +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; + if (sigprocmask_return_val != 1) { + printf("FAIL: sigprocmask() returned before signal was delivered.\n"); + exit(EXIT_FAILURE); + } +} + +int main() +{ + struct sigaction act; + sigset_t blocked_set1; + sigemptyset(&blocked_set1); + sigaddset(&blocked_set1, SIGABRT); + + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + int status; + + status = sigaction(SIGABRT, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigprocmask(SIG_SETMASK, &blocked_set1, NULL); + ERROR_IF(sigprocmask, status, == -1); + + status = raise(SIGABRT); + ERROR_IF(raise, status, == -1); + + sigprocmask_return_val = sigprocmask(SIG_UNBLOCK, &blocked_set1, NULL); + + ERROR_IF(sigprocmask, sigprocmask_return_val, != 0); + + ERROR_IF(raise, handler_called, != 1); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/sigprocmask-9.c b/tests/signals/sigprocmask-9.c new file mode 100644 index 0000000000..168eed88c4 --- /dev/null +++ b/tests/signals/sigprocmask-9.c @@ -0,0 +1,28 @@ +#include "../test_helpers.h" +#include +#include +#include +#include + +// Attempt to add SIGKILL and SIGSTOP to the process's signal mask and +// verify that: +// - They do not get added. +// - sigprocmask() does not return -1. + +int main() { + sigset_t set1, set2; + int ret; + + sigemptyset(&set1); + sigemptyset(&set2); + sigaddset(&set1, SIGKILL); + sigaddset(&set1, SIGSTOP); + + ret = sigprocmask(SIG_SETMASK, &set1, NULL); + ERROR_IF(sigprocmask, ret, == -1); + ret = sigprocmask(SIG_SETMASK, NULL, &set2); + ERROR_IF(sigprocmask, ret, == -1); + + assert(!sigismember(&set2, SIGKILL)); + assert(!sigismember(&set2, SIGSTOP)); +} diff --git a/tests/signals/sigprocmask-block.c b/tests/signals/sigprocmask-block.c new file mode 100644 index 0000000000..b1736bfa91 --- /dev/null +++ b/tests/signals/sigprocmask-block.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; +} + +int sigprocmask_block(int signum) +{ + int defaultsig = SIGALRM; + if (signum == SIGALRM) { + defaultsig = SIGHUP; + } + struct sigaction act; + sigset_t blocked_set1, blocked_set2, pending_set; + sigemptyset(&blocked_set1); + sigemptyset(&blocked_set2); + sigaddset(&blocked_set1, signum); + sigaddset(&blocked_set2, defaultsig); + + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + int status; + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigaction(defaultsig, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigprocmask(SIG_SETMASK, &blocked_set1, NULL); + ERROR_IF(sigprocmask, status, == -1); + + status = sigprocmask(SIG_BLOCK, &blocked_set2, NULL); + ERROR_IF(sigprocmask, status, == -1); + + ERROR_IF(raise, signum, == -1); + ERROR_IF(raise, defaultsig, == -1); + + if (handler_called) { + printf("FAIL: Signal was not blocked\n"); + exit(EXIT_FAILURE); + } + + status = sigpending(&pending_set); + ERROR_IF(sigpending, status, == -1); + + status = sigismember(&pending_set, signum); + ERROR_IF(sigismember, status, != 1); + status = sigismember(&pending_set, defaultsig); + ERROR_IF(sigismember, status, != 1); + + act.sa_handler = SIG_IGN; + sigaction(signum, &act, 0); + sigaction(defaultsig, &act, 0); + + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; +} + +int sigprocmask_block(int signum) +{ + struct sigaction act; + sigset_t blocked_set, pending_set; + sigemptyset(&blocked_set); + sigaddset(&blocked_set, signum); + + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + int status; + status = sigaction(signum, &act, 0); + ERROR_IF(sigaction, status, == -1); + + status = sigprocmask(SIG_SETMASK, &blocked_set, NULL); + ERROR_IF(sigprocmask, status, == -1); + + status = raise(signum); + ERROR_IF(raise, status, == -1); + + if (handler_called) { + printf("FAIL: Signal was not blocked\n"); + exit(EXIT_FAILURE); + } + + status = sigpending(&pending_set); + ERROR_IF(sigpending, status, == -1); + + status = sigismember(&pending_set, signum); + ERROR_IF(sigismember, status, != 1); + + act.sa_handler = SIG_IGN; + sigaction(signum, &act, 0); + + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +#define _XOPEN_SOURCE 700 + +volatile sig_atomic_t handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + handler_called = 1; +} + +int sigrelse_test(int signum) +{ + // needs to be reset + handler_called = 0; + + struct sigaction act; + + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + int status; + status = sigaction(signum, &act, NULL); + ERROR_IF(sigaction, status, == -1); + + status = sighold(signum); + ERROR_IF(sighold, status, == -1); + + assert(handler_called == 0); + + status = raise(signum); + ERROR_IF(raise, status, == -1); + + assert(handler_called == 0); + + status = sigrelse(signum); + ERROR_IF(sigrelse, status, == -1); + + assert(handler_called == 1); + // if (handler_called) { + // printf("PASS: %d successfully removed from signal mask\n", signum); + // handler_called = 0; + // return EXIT_SUCCESS; + // } + // printf("FAIL\n"); + // exit(EXIT_FAILURE); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include "../test_helpers.h" + +int main() +{ + int status; + status = (int)sigrelse(SIGABRT); + ERROR_IF(sigrelse, status, != 0); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/sigrelse-3.c b/tests/signals/sigrelse-3.c new file mode 100644 index 0000000000..980bca35bd --- /dev/null +++ b/tests/signals/sigrelse-3.c @@ -0,0 +1,14 @@ +#include +#include +#include +#include +#include "../test_helpers.h" + +int main() +{ + int status; + status = (int)sigrelse(100000); + ERROR_IF(sigrelse, status, != -1); + ERROR_IF(sigrelse, errno, != EINVAL); + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/tests/signals/sigset-1.c b/tests/signals/sigset-1.c new file mode 100644 index 0000000000..17f261d482 --- /dev/null +++ b/tests/signals/sigset-1.c @@ -0,0 +1,48 @@ +#define _XOPEN_SOURCE 600 + +#include +#include +#include + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + printf("SIGURG called. Inside handler\n"); + handler_called = 1; +} + +int sigset_test(int signum) +{ + + struct sigaction act; + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + + if (sigaction(signum, &act, 0) != 0) { + perror("Unexpected error while using sigaction()"); + exit(EXIT_FAILURE); + } + + if (sigset(signum,SIG_DFL) != sig_handler) { + perror("Unexpected error while using signal()"); + exit(EXIT_FAILURE); + } + + raise(signum); + + if (handler_called == 1) { + printf("Test FAILED: handler was called even though default was expected\n"); + exit(EXIT_FAILURE); + } + printf("test passed, the signal was ignored\n"); + return EXIT_SUCCESS; +} + +int main(){ + sigset_test(SIGURG); + return EXIT_SUCCESS; +} + diff --git a/tests/signals/sigset-10.c b/tests/signals/sigset-10.c new file mode 100644 index 0000000000..04986b739e --- /dev/null +++ b/tests/signals/sigset-10.c @@ -0,0 +1,27 @@ +#define _XOPEN_SOURCE 600 + +#include +#include +#include +#include +#include +#include "../test_helpers.h" + +int main() +{ + void (*status) (int); + status = sigset(SIGKILL,SIG_IGN); + assert(status == SIG_ERR); + assert(errno == EINVAL); + // if (sigset(SIGKILL,SIG_IGN) == SIG_ERR) { + // if (errno != EINVAL) { + // printf("Test FAILED: sigset() returned SIG_ERR but didn't set errno to EINVAL\n"); + // exit(EXIT_FAILURE); + // } + // } else { + // printf("Test FAILED: sigset() didn't return SIG_ERROR even though SIGKILL was passed to it\n"); + // exit(EXIT_FAILURE); + // } + // printf("test passed: error was set successfully\n"); + return EXIT_SUCCESS; +} diff --git a/tests/signals/sigset-2.c b/tests/signals/sigset-2.c new file mode 100644 index 0000000000..35aacbcb13 --- /dev/null +++ b/tests/signals/sigset-2.c @@ -0,0 +1,54 @@ +#define _XOPEN_SOURCE 600 + +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + printf("SIGUSR1 called. Inside handler\n"); + handler_called = 1; +} + +int sigset_test2(int signum) +{ + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = sig_handler; + sigemptyset(&act.sa_mask); + + if (sigaction(signum, &act, 0) != 0) { + perror("Unexpected error while using sigaction()"); + exit(EXIT_FAILURE); + } + + if (sigset(signum,SIG_IGN) != sig_handler) { + perror("Unexpected error while using signal()"); + exit(EXIT_FAILURE); + } + + raise(signum); + + if (handler_called == 1) { + printf("Test FAILED: handler was called even though ignore was expected\n"); + exit(EXIT_FAILURE); + } + printf("test %d passed, the signal was ignored\n", signum); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int handler_called = 0; + +void sig_handler(int signo) +{ + (void) signo; + // printf("SIGCHLD called. Inside handler\n"); + handler_called = 1; +} + +int sigset_test3(int signum) +{ + if (sigset(signum, sig_handler) == SIG_ERR) { + perror("Unexpected error while using sigset()"); + exit(EXIT_FAILURE); + } + + raise(signum); + + if (handler_called != 1) { + printf("Test FAILED: handler wasn't called even though it was expected\n"); + exit(EXIT_FAILURE); + } + printf("test %d passed, handler was called\n", signum); + handler_called = 0; + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +int signal_blocked = 0; +int count = 1; + +void sig_handler(int signo) +{ + (void) signo; + // printf("SIGCHLD called. Inside handler\n"); + sigset_t mask; + sigprocmask(SIG_SETMASK, NULL, &mask); + if (count == SIGKILL || count == SIGSTOP){ + count++; + } + if(sigismember(&mask, count)) { + signal_blocked = 1; + } + count++; +} + +int sigset_test4(int signum) +{ + if (sigset(signum, sig_handler) == SIG_ERR) { + perror("Unexpected error while using sigset()"); + exit(EXIT_FAILURE); + } + + raise(signum); + + if (signal_blocked != 1) { + printf("Test FAILED: signal was not added to the mask before the handler was executed\n"); + exit(EXIT_FAILURE); + } + signal_blocked = 0; + printf("test %d passed: the singal was added to the mask before the handler was executed\n", signum); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +#define NUMSIGNALS 26 + +bool is_empty(sigset_t *set) { + + int i; + int siglist[25] = {SIGABRT, SIGALRM, SIGBUS, SIGCHLD, + SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, + SIGPIPE, SIGQUIT, SIGSEGV, + SIGTERM, SIGTSTP, SIGTTIN, SIGTTOU, + SIGUSR1, SIGUSR2, SIGPROF, SIGSYS, + SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ }; + + for (i=0; i<25; i++) { + if (sigismember(set, siglist[i]) != 0) + return false; + } + return true; +} + +void sig_handler(int signo) +{ + printf("%d called. Inside handler\n", signo); +} + +int sigset_test5(int signum) +{ + sigset_t mask; + sigemptyset(&mask); + + sigprocmask(SIG_SETMASK, &mask, NULL); + void (*status) (int); + + status = sigset(signum, sig_handler); + ERROR_IF(sigset, status, == SIG_ERR); + // if (sigset(signum, sig_handler) == SIG_ERR) { + // perror("Unexpected error while using sigset()"); + // exit(EXIT_FAILURE); + // } + + raise(signum); + sigprocmask(SIG_SETMASK, NULL, &mask); + bool status1 = is_empty(&mask); + assert(status1); + // if (is_empty(&mask) != 1) { + // printf("Test FAILED: signal mask should be empty\n"); + // exit(EXIT_FAILURE); + // } + // printf("sig %d was successfully removed from the mask when handler returned\n", signum); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i +#include +#include +#include "signals_list.h" +#include "../test_helpers.h" + +void sig_handler(int signo) +{ + (void) signo; + printf("SIGUSR1 called. Inside handler\n"); +} + +int sigset_test9(int signum) +{ + struct sigaction act; + act.sa_flags = 0; + act.sa_handler = sig_handler; + sigemptyset(&act.sa_mask); + + if (sigaction(signum, &act, 0) != 0) { + perror("Unexpected error while using sigaction()"); + exit(EXIT_FAILURE); + } + + if (sigset(signum,SIG_DFL) != sig_handler) { + printf("Test FAILED: sigset didn't return myhandler even though it was SIGUSR1's original disposition\n"); + exit(EXIT_FAILURE); + } + printf("test %d passed \n", signum); + return EXIT_SUCCESS; +} + +int main(){ + for (int i=1; i