xref: /dragonfly/test/stress/stress2/misc/kevent4.sh (revision 2b3f93ea)
1#!/bin/sh
2
3#
4# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
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# $FreeBSD$
29#
30# Test scenario by kib@
31
32. ../default.cfg
33
34odir=`pwd`
35
36cd /tmp
37sed '1,/^EOF/d' < $odir/$0 > kevent.c
38cc -o kevent -Wall kevent.c -pthread
39rm -f kevent.c
40
41cd $odir/..
42export runRUNTIME=3m
43./run.sh &
44rpid=$!
45
46cd $RUNDIR
47/tmp/kevent $rpid &
48
49sleep 120
50kill $rpid
51kill $!
52rm -f /tmp/kevent
53
54exit
55EOF
56// $FreeBSD$
57
58#include <unistd.h>
59#include <sys/types.h>
60#include <sys/event.h>
61#include <errno.h>
62#include <string.h>
63#include <stdio.h>
64#include <stdlib.h>
65#ifndef true
66# define true 1
67#endif
68
69int kq;
70
71void
72err(const char *msg, int err_no)
73{
74	fprintf(stderr, "%s: %s\n", msg, strerror(err_no));
75	exit(1);
76}
77
78void
79init_kq()
80{
81	kq = kqueue();
82	if (kq == -1)
83		err("kqueue", errno);
84}
85
86void
87add_watch(pid_t pid)
88{
89	struct kevent kev;
90	bzero(&kev, sizeof(kev));
91	kev.ident = pid;
92	kev.flags = EV_ADD | EV_ENABLE;
93	kev.filter = EVFILT_PROC;
94	kev.fflags = NOTE_EXIT | NOTE_FORK | NOTE_EXEC | NOTE_TRACK;
95
96	while (true) {
97		int res = kevent(kq, &kev, 1, NULL, 0, NULL);
98		if (res == -1) {
99			if (errno == EINTR)
100				continue;
101			if (errno == ESRCH)
102				break;
103
104			int err_no = errno;
105			char msg[64];
106			snprintf(msg, sizeof(msg),
107				 "kevent - add watch for pid %u", pid);
108			err(msg, err_no);
109		}
110		else
111			break;
112	}
113}
114
115void
116del_watch(pid_t pid)
117{
118	struct kevent kev;
119	bzero(&kev, sizeof(kev));
120	kev.ident = pid;
121	kev.flags = EV_DELETE;
122	kev.filter = EVFILT_PROC;
123
124	while (true) {
125		int res = kevent(kq, &kev, 1, NULL, 0, NULL);
126		if (res == -1) {
127			if (errno == EINTR)
128				continue;
129			if (errno == ESRCH)
130				break;
131
132			int err_no = errno;
133			char msg[64];
134			snprintf(msg, sizeof(msg),
135				 "kevent - del watch for pid %u", pid);
136			err(msg, err_no);
137		}
138		else
139			break;
140	}
141}
142
143void polling()
144{
145	struct kevent kev[10];
146	pid_t pid;
147	int i;
148
149	while (true) {
150		bzero(&kev, sizeof(kev));
151		int res = kevent(kq, NULL, 0, kev,
152				 sizeof(kev) / sizeof(kev[0]), NULL);
153		if (res == -1) {
154			if (errno == EINTR)
155				continue;
156
157			if (errno == ESRCH)
158				continue;
159
160			err("kevent", errno);
161		}
162
163		for (i = 0; i < res; i++) {
164			pid = kev[i].ident;
165			if (kev[i].fflags & NOTE_CHILD) {
166				add_watch(pid);
167				printf("%u - new process, parent %u\n", pid, kev[i].data);
168			}
169			if (kev[i].fflags & NOTE_FORK) {
170				printf("%u forked\n", pid);
171			}
172			if (kev[i].fflags & NOTE_EXEC) {
173				printf("%u called exec\n", pid);
174			}
175			if (kev[i].fflags & NOTE_EXIT) {
176				printf("%u exited\n", pid);
177//  				del_watch(pid);
178			}
179			if (kev[i].fflags & NOTE_TRACK) {
180				printf("%u forked - track\n", pid);
181			}
182			if (kev[i].fflags & NOTE_TRACKERR) {
183				fprintf(stderr, "%u - track error\n", pid);
184			}
185		}
186	}
187}
188
189int main(int argc, char *argv[])
190{
191	if (argc != 2) {
192		fprintf(stderr, "pid ?\n");
193		return (2);
194	}
195	pid_t parent = atoi(argv[1]);
196
197	init_kq();
198	add_watch(parent);
199	polling();
200
201	return (0);
202}
203