xref: /freebsd/tools/test/stress2/misc/sigaltstack.sh (revision 7ef62cebc2f965b0f640263e179276928885e33d)
1#!/bin/sh
2
3# sigaltstack(2) regression test by Steven Hartland <killing@multiplay.co.uk>
4# Wrong altsigstack clearing on exec
5# https://github.com/golang/go/issues/15658#issuecomment-287276856
6
7# Fixed by r315453
8
9cd /tmp
10cat > test-sigs.c <<EOF
11#include <errno.h>
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <unistd.h>
17#include <time.h>
18#include <pthread.h>
19
20extern char **environ;
21
22static void
23die(const char *s)
24{
25       perror(s);
26       exit(EXIT_FAILURE);
27}
28
29static void
30setstack(void *arg __unused)
31{
32	stack_t ss;
33
34	ss.ss_sp = malloc(SIGSTKSZ);
35	if (ss.ss_sp == NULL)
36		die("malloc");
37
38	ss.ss_size = SIGSTKSZ;
39	ss.ss_flags = 0;
40	if (sigaltstack(&ss, NULL) < 0)
41		die("sigaltstack set");
42}
43
44static void *
45thread_exec(void *arg)
46{
47	struct timespec ts = {0, 1000};
48	char *argv[] = {"./test-sigs", "no-more", 0};
49
50	setstack(arg);
51	nanosleep(&ts, NULL);
52
53	execve(argv[0], &argv[0], environ);
54	die("exec failed");
55
56	return NULL;
57}
58
59static void *
60thread_sleep(void *arg __unused)
61{
62	sleep(10);
63
64	return NULL;
65}
66
67int
68main(int argc, char** argv __unused)
69{
70	int j;
71	pthread_t tid1, tid2;
72
73	if (argc != 1) {
74		stack_t ss;
75
76		if (sigaltstack(NULL, &ss) < 0)
77			die("sigaltstack get");
78
79		if (ss.ss_sp != NULL || ss.ss_flags != SS_DISABLE ||
80		    ss.ss_size != 0) {
81			fprintf(stderr, "invalid signal stack after execve: "
82			    "ss_sp=%p ss_size=%lu ss_flags=0x%x\n", ss.ss_sp,
83			    (unsigned long)ss.ss_size,
84			    (unsigned int)ss.ss_flags);
85			return 1;
86		}
87
88		printf("valid signal stack is valid after execve\n");
89
90		return 0;
91	}
92
93	// We have to use two threads to ensure that can detect the
94	// issue when new threads are added to the head (pre 269095)
95	// and the tail of the process thread list.
96	j = pthread_create(&tid1, NULL, thread_exec, NULL);
97	if (j != 0) {
98	       errno = j;
99	       die("pthread_create");
100	}
101
102	j = pthread_create(&tid2, NULL, thread_sleep, NULL);
103	if (j != 0) {
104	       errno = j;
105	       die("pthread_create");
106	}
107
108	j = pthread_join(tid1, NULL);
109	if (j != 0) {
110		errno = j;
111		die("pthread_join");
112	}
113
114	j = pthread_join(tid2, NULL);
115	if (j != 0) {
116		errno = j;
117	}
118
119	return 0;
120}
121EOF
122
123cc -o test-sigs -Wall -Wextra -O2 -g test-sigs.c -lpthread || exit 1
124./test-sigs
125s=$?
126
127rm -f test-sigs test-sigs.c
128exit $s
129