xref: /freebsd/tools/test/stress2/misc/ptrace6.sh (revision 3c4ba5f55438f7afd4f4b0b56f88f2bb505fd6a6)
1#!/bin/sh
2
3#
4# Copyright (c) 2016 EMC Corp.
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28
29# panic: Assertion TD_IS_SLEEPING(td) failed at subr_sleepqueue.c:958.
30# Fixed by r303426.
31
32. ../default.cfg
33
34dir=/tmp
35odir=`pwd`
36cd $dir
37sed '1,/^EOF/d' < $odir/$0 > $dir/ptrace6.c
38mycc -o ptrace6 -Wall -Wextra -O0 -g ptrace6.c -pthread || exit 1
39rm -f ptrace6.c
40cd $odir
41
42/tmp/ptrace6
43s=$?
44
45while pgrep -q swap; do
46	pkill -9 swap
47done
48rm -rf /tmp/ptrace6
49exit $s
50
51EOF
52#include <sys/param.h>
53#include <sys/ptrace.h>
54#include <sys/stat.h>
55#include <sys/wait.h>
56
57#include <err.h>
58#include <errno.h>
59#include <fcntl.h>
60#include <pthread.h>
61#include <signal.h>
62#include <stdio.h>
63#include <stdlib.h>
64#include <time.h>
65#include <unistd.h>
66
67static pid_t pid;
68static pthread_barrier_t barr;
69static int cont;
70static int state;
71
72#define PARALLEL 4
73#define RUNTIME (4 * 60)
74
75static void
76ahandler(int i __unused)
77{
78	system("ps -Hl");
79	fprintf(stderr, "SIGALRM state %d, pid %d\n", state, pid);
80	exit(1);
81}
82
83static void
84handler(int i __unused)
85{
86}
87
88static void *
89t1(void *data __unused)
90{
91	int status;
92
93	while (cont == 1) {
94		state = 1;
95		if (ptrace(PT_ATTACH, pid, 0, 0) == -1)
96			err(1, "ptrace(%d)", pid);
97
98		state = 2;
99		if (waitpid(pid, &status, 0) == -1)
100			err(1, "waitpid");
101		else if (!WIFSTOPPED(status))
102			errx(1, "failed to stop child");
103		state = 3;
104		if (ptrace(PT_DETACH, pid, 0, 0) == -1)
105			err(1, "ptrace");
106		state = 4;
107		usleep(arc4random() % 200);
108	}
109
110	return (NULL);
111}
112
113static void *
114t2(void *data __unused)
115{
116	while (cont == 1) {
117		if (kill(pid, SIGHUP) == -1)
118			err(1, "kill");
119		usleep(arc4random() % 200);
120	}
121
122	return (NULL);
123}
124
125static void
126test(void)
127{
128	pthread_t tid[2];
129	struct sigaction sa;
130	int r;
131
132	r = pthread_barrier_wait(&barr);
133	if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
134	    errc(1, r, "pthread_barrier_wait");
135
136	sa.sa_handler = ahandler;
137	sigemptyset(&sa.sa_mask);
138	sa.sa_flags = 0;
139	if (sigaction(SIGALRM, &sa, NULL) == -1)
140		err(1, "sigaction");
141	alarm(RUNTIME + 60);
142
143	sa.sa_handler = handler;
144	sigemptyset(&sa.sa_mask);
145	sa.sa_flags = 0;
146	if (sigaction(SIGHUP, &sa, NULL) == -1)
147		err(1, "sigaction");
148
149	if ((pid = fork()) == 0) {
150		for(;;)
151			usleep(arc4random() % 1000);
152
153		_exit(0);
154	}
155
156	cont = 1;
157	if ((r = pthread_create(&tid[0], NULL, t1, NULL)) == -1)
158		errc(1, r, "pthread_create");
159	if ((r = pthread_create(&tid[1], NULL, t2, NULL)) == -1)
160		errc(1, r, "pthread_create");
161
162	sleep(RUNTIME);
163
164	cont = 0;
165	if ((r = pthread_join(tid[0], NULL)) == -1)
166			errc(1, r, "pthread_join");
167	if ((r = pthread_join(tid[1], NULL)) == -1)
168			errc(1, r, "pthread_join");
169	if (kill(pid, SIGKILL) != 0)
170		err(1, "kill(%d)", pid);
171	waitpid(pid, NULL, 0);
172
173	exit(0);
174}
175
176int
177main(void)
178{
179	pthread_barrierattr_t attr;
180	int e, i, pids[PARALLEL], r, status;
181
182	if ((r = pthread_barrierattr_init(&attr)) != 0)
183		errc(1, r, "pthread_barrierattr_init");
184	if ((r = pthread_barrierattr_setpshared(&attr,
185	    PTHREAD_PROCESS_SHARED)) != 0)
186		errc(1, r, "pthread_barrierattr_setpshared");
187	if ((r = pthread_barrier_init(&barr, &attr, PARALLEL)) != 0)
188		errc(1, r, "pthread_barrier_init");
189
190	e = 0;
191	for (i = 0; i < PARALLEL; i++) {
192		if ((pids[i] = fork()) == 0)
193			test();
194	}
195	for (i = 0; i < PARALLEL; i++) {
196		waitpid(pids[i], &status, 0);
197		e += status == 0 ? 0 : 1;
198	}
199
200	if ((r = pthread_barrier_destroy(&barr)) > 0)
201		errc(1, r, "pthread_barrier_destroy");
202
203	return (e);
204}
205