View | Details | Raw Unified | Return to bug 170346 | Differences between
and this patch

Collapse All | Expand All

(-)sys/sys/wait.h (+5 lines)
Lines 80-85 Link Here
80
#define	WSTOPPED	WUNTRACED   /* SUS compatibility */
80
#define	WSTOPPED	WUNTRACED   /* SUS compatibility */
81
#define	WCONTINUED	4	/* Report a job control continued process. */
81
#define	WCONTINUED	4	/* Report a job control continued process. */
82
#define	WNOWAIT		8	/* Poll only. Don't delete the proc entry. */
82
#define	WNOWAIT		8	/* Poll only. Don't delete the proc entry. */
83
#define WEXITED		16	/* Wait for exited processes. (SUS) */
84
#define WTRAPPED	32	/* Wait for a process to hit a trap or a breakpoint. (Solaris) */
83
85
84
#if __BSD_VISIBLE
86
#if __BSD_VISIBLE
85
#define	WLINUXCLONE 0x80000000	/* Wait for kthread spawned from linux_clone. */
87
#define	WLINUXCLONE 0x80000000	/* Wait for kthread spawned from linux_clone. */
Lines 95-108 Link Here
95
97
96
#ifndef _KERNEL
98
#ifndef _KERNEL
97
#include <sys/types.h>
99
#include <sys/types.h>
100
#include <sys/signal.h>
98
101
99
__BEGIN_DECLS
102
__BEGIN_DECLS
100
pid_t	wait(int *);
103
pid_t	wait(int *);
101
pid_t	waitpid(pid_t, int *, int);
104
pid_t	waitpid(pid_t, int *, int);
105
int	waitid(idtype_t, id_t, siginfo_t *, int);
102
#if __BSD_VISIBLE
106
#if __BSD_VISIBLE
103
struct rusage;
107
struct rusage;
104
pid_t	wait3(int *, int, struct rusage *);
108
pid_t	wait3(int *, int, struct rusage *);
105
pid_t	wait4(pid_t, int *, int, struct rusage *);
109
pid_t	wait4(pid_t, int *, int, struct rusage *);
110
pid_t	wait6(idtype_t, id_t, int *, int, struct rusage *, siginfo_t *);
106
#endif
111
#endif
107
__END_DECLS
112
__END_DECLS
108
#endif /* !_KERNEL */
113
#endif /* !_KERNEL */
(-)sys/sys/syscallsubr.h (+2 lines)
Lines 233-238 Link Here
233
	    enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg);
233
	    enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg);
234
int	kern_wait(struct thread *td, pid_t pid, int *status, int options,
234
int	kern_wait(struct thread *td, pid_t pid, int *status, int options,
235
	    struct rusage *rup);
235
	    struct rusage *rup);
236
int	kern_wait6(struct thread *td, idtype_t idtype, id_t id, int *status,
237
		   int options, struct rusage *rup, siginfo_t *sip);
236
int	kern_writev(struct thread *td, int fd, struct uio *auio);
238
int	kern_writev(struct thread *td, int fd, struct uio *auio);
237
int	kern_socketpair(struct thread *td, int domain, int type, int protocol,
239
int	kern_socketpair(struct thread *td, int domain, int type, int protocol,
238
	    int *rsv);
240
	    int *rsv);
(-)sys/bsm/audit_kevents.h (+1 lines)
Lines 602-607 Link Here
602
#define	AUE_PDKILL		43198	/* FreeBSD. */
602
#define	AUE_PDKILL		43198	/* FreeBSD. */
603
#define	AUE_PDGETPID		43199	/* FreeBSD. */
603
#define	AUE_PDGETPID		43199	/* FreeBSD. */
604
#define	AUE_PDWAIT		43200	/* FreeBSD. */
604
#define	AUE_PDWAIT		43200	/* FreeBSD. */
605
#define	AUE_WAIT6		43201	/* FreeBSD. */
605
606
606
/*
607
/*
607
 * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
608
 * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
(-)sys/kern/syscalls.master (-2 / +6 lines)
Lines 72-78 Link Here
72
6	AUE_CLOSE	STD	{ int close(int fd); }
72
6	AUE_CLOSE	STD	{ int close(int fd); }
73
7	AUE_WAIT4	STD	{ int wait4(int pid, int *status, \
73
7	AUE_WAIT4	STD	{ int wait4(int pid, int *status, \
74
				    int options, struct rusage *rusage); } \
74
				    int options, struct rusage *rusage); } \
75
				    wait4 wait_args int
75
				    wait4 wait4_args int
76
8	AUE_CREAT	COMPAT	{ int creat(char *path, int mode); }
76
8	AUE_CREAT	COMPAT	{ int creat(char *path, int mode); }
77
9	AUE_LINK	STD	{ int link(char *path, char *link); }
77
9	AUE_LINK	STD	{ int link(char *path, char *link); }
78
10	AUE_UNLINK	STD	{ int unlink(char *path); }
78
10	AUE_UNLINK	STD	{ int unlink(char *path); }
Lines 368-374 Link Here
368
190	AUE_LSTAT	STD	{ int lstat(char *path, struct stat *ub); }
368
190	AUE_LSTAT	STD	{ int lstat(char *path, struct stat *ub); }
369
191	AUE_PATHCONF	STD	{ int pathconf(char *path, int name); }
369
191	AUE_PATHCONF	STD	{ int pathconf(char *path, int name); }
370
192	AUE_FPATHCONF	STD	{ int fpathconf(int fd, int name); }
370
192	AUE_FPATHCONF	STD	{ int fpathconf(int fd, int name); }
371
193	AUE_NULL	UNIMPL	nosys
371
193	AUE_WAIT6	STD	{ int wait6(int idtype, int id, \
372
					    int *status, int options, \
373
					    struct rusage *rusage, \
374
					    siginfo_t *info); } \
375
					wait6 wait6_args int
372
194	AUE_GETRLIMIT	STD	{ int getrlimit(u_int which, \
376
194	AUE_GETRLIMIT	STD	{ int getrlimit(u_int which, \
373
				    struct rlimit *rlp); } getrlimit \
377
				    struct rlimit *rlp); } getrlimit \
374
				    __getrlimit_args int
378
				    __getrlimit_args int
(-)lib/libc/include/namespace.h (+1 lines)
Lines 229-234 Link Here
229
#define		socketpair			_socketpair
229
#define		socketpair			_socketpair
230
#define		usleep				_usleep
230
#define		usleep				_usleep
231
#define		wait4				_wait4
231
#define		wait4				_wait4
232
#define		wait6				_wait6
232
#define		waitpid				_waitpid
233
#define		waitpid				_waitpid
233
#define		write				_write
234
#define		write				_write
234
#define		writev				_writev
235
#define		writev				_writev
(-)lib/libc/include/un-namespace.h (+1 lines)
Lines 210-215 Link Here
210
#undef		socketpair
210
#undef		socketpair
211
#undef		usleep
211
#undef		usleep
212
#undef		wait4
212
#undef		wait4
213
#undef		wait6
213
#undef		waitpid
214
#undef		waitpid
214
#undef		write
215
#undef		write
215
#undef		writev
216
#undef		writev
(-)lib/libc/gen/Makefile.inc (-1 / +1 lines)
Lines 34-40 Link Here
34
	syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \
34
	syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \
35
	ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis.c \
35
	ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis.c \
36
	usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
36
	usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
37
	wordexp.c
37
	waitid.c wordexp.c
38
38
39
CANCELPOINTS_SRCS=sem.c sem_new.c
39
CANCELPOINTS_SRCS=sem.c sem_new.c
40
.for src in ${CANCELPOINTS_SRCS}
40
.for src in ${CANCELPOINTS_SRCS}
(-)sys/cddl/contrib/opensolaris/uts/common/sys/procset.h (+4 lines)
Lines 51-56 Link Here
51
#define	P_INITUID	0
51
#define	P_INITUID	0
52
#define	P_INITPGID	0
52
#define	P_INITPGID	0
53
53
54
#ifndef _IDTYPE_T_DECLARED
54
55
55
/*
56
/*
56
 *	The following defines the values for an identifier type.  It
57
 *	The following defines the values for an identifier type.  It
Lines 81-86 Link Here
81
	P_PSETID	/* Processor set identifier		*/
82
	P_PSETID	/* Processor set identifier		*/
82
} idtype_t;
83
} idtype_t;
83
84
85
#define	_IDTYPE_T_DECLARED
86
87
#endif
84
88
85
/*
89
/*
86
 *	The following defines the operations which can be performed to
90
 *	The following defines the operations which can be performed to
(-)sys/sys/proc.h (-2 / +1 lines)
Lines 879-886 Link Here
879
void	procinit(void);
879
void	procinit(void);
880
void	proc_linkup0(struct proc *p, struct thread *td);
880
void	proc_linkup0(struct proc *p, struct thread *td);
881
void	proc_linkup(struct proc *p, struct thread *td);
881
void	proc_linkup(struct proc *p, struct thread *td);
882
void	proc_reap(struct thread *td, struct proc *p, int *status, int options,
882
void	proc_reap(struct thread *td, struct proc *p, int *status, int options);
883
	    struct rusage *rusage);
884
void	proc_reparent(struct proc *child, struct proc *newparent);
883
void	proc_reparent(struct proc *child, struct proc *newparent);
885
struct	pstats *pstats_alloc(void);
884
struct	pstats *pstats_alloc(void);
886
void	pstats_fork(struct pstats *src, struct pstats *dst);
885
void	pstats_fork(struct pstats *src, struct pstats *dst);
(-)lib/libc/gen/Symbol.map (+1 lines)
Lines 384-389 Link Here
384
	 fdlopen;
384
	 fdlopen;
385
	__FreeBSD_libc_enter_restricted_mode;
385
	__FreeBSD_libc_enter_restricted_mode;
386
	getcontextx;
386
	getcontextx;
387
	waitid;
387
};
388
};
388
389
389
FBSDprivate_1.0 {
390
FBSDprivate_1.0 {
(-)sys/sys/types.h (+38 lines)
Lines 142-147 Link Here
142
#define	_ID_T_DECLARED
142
#define	_ID_T_DECLARED
143
#endif
143
#endif
144
144
145
#ifndef _IDTYPE_T_DECLARED
146
147
typedef enum
148
#if !defined(_XPG4_2) || defined(__EXTENSIONS__)
149
	idtype		/* pollutes XPG4.2 namespace */
150
#endif
151
		{
152
	/*
153
	 * These names were mostly lifted from Solaris source code
154
	 * and still use Solaris style naming to avoid breaking any
155
	 * OpenSolaris code which has been ported to FreeBSD.
156
	 * There is no clear FreeBSD counterpart for all of the names.
157
	 * OTOH some have a clear correspondence to FreeBSD entities.
158
	 */
159
	
160
	P_PID,		/* A process identifier.		*/
161
	P_PPID,		/* A parent process identifier.		*/
162
	P_PGID,		/* A process group (job control group)	*/
163
			/* identifier.				*/
164
	P_SID,		/* A session identifier.		*/
165
	P_CID,		/* A scheduling class identifier.	*/
166
	P_UID,		/* A user identifier.			*/
167
	P_GID,		/* A group identifier.			*/
168
	P_ALL,		/* All processes.			*/
169
	P_LWPID,	/* An LWP identifier.			*/
170
	P_TASKID,	/* A task identifier.			*/
171
	P_PROJID,	/* A project identifier.		*/
172
	P_POOLID,	/* A pool identifier.			*/
173
	P_ZONEID,	/* A zone identifier.			*/
174
	P_CTID,		/* A (process) contract identifier.	*/
175
	P_CPUID,	/* CPU identifier.			*/
176
	P_PSETID	/* Processor set identifier		*/
177
} idtype_t;		/* The type of id_t we are using.	*/
178
179
#define	_IDTYPE_T_DECLARED
180
#endif
181
182
145
#ifndef _INO_T_DECLARED
183
#ifndef _INO_T_DECLARED
146
typedef	__ino_t		ino_t;		/* inode number */
184
typedef	__ino_t		ino_t;		/* inode number */
147
#define	_INO_T_DECLARED
185
#define	_INO_T_DECLARED
(-)lib/libc/sys/wait.2 (-23 / +281 lines)
Lines 34-42 Link Here
34
.Sh NAME
34
.Sh NAME
35
.Nm wait ,
35
.Nm wait ,
36
.Nm waitpid ,
36
.Nm waitpid ,
37
.Nm waitid ,
38
.Nm wait3 ,
37
.Nm wait4 ,
39
.Nm wait4 ,
38
.Nm wait3
40
.Nm wait6
39
.Nd wait for process termination
41
.Nd wait for processes to change status
40
.Sh LIBRARY
42
.Sh LIBRARY
41
.Lb libc
43
.Lb libc
42
.Sh SYNOPSIS
44
.Sh SYNOPSIS
Lines 46-57 Link Here
46
.Fn wait "int *status"
48
.Fn wait "int *status"
47
.Ft pid_t
49
.Ft pid_t
48
.Fn waitpid "pid_t wpid" "int *status" "int options"
50
.Fn waitpid "pid_t wpid" "int *status" "int options"
51
.In sys/signal.h
52
.Ft int
53
.Fn waitid "idtype_t idtype" "id_t id" "siginfo_t *info" "int options"
49
.In sys/time.h
54
.In sys/time.h
50
.In sys/resource.h
55
.In sys/resource.h
51
.Ft pid_t
56
.Ft pid_t
52
.Fn wait3 "int *status" "int options" "struct rusage *rusage"
57
.Fn wait3 "int *status" "int options" "struct rusage *rusage"
53
.Ft pid_t
58
.Ft pid_t
54
.Fn wait4 "pid_t wpid" "int *status" "int options" "struct rusage *rusage"
59
.Fn wait4 "pid_t wpid" "int *status" "int options" "struct rusage *rusage"
60
.Ft pid_t
61
.Fn wait6 "idtype_t idtype" "id_t id" "int *status" "int options" "struct rusage *rusage" "siginfo_t *infop"
55
.Sh DESCRIPTION
62
.Sh DESCRIPTION
56
The
63
The
57
.Fn wait
64
.Fn wait
Lines 89-113 Link Here
89
The other wait functions are implemented using
96
The other wait functions are implemented using
90
.Fn wait4 .
97
.Fn wait4 .
91
.Pp
98
.Pp
99
The broadest interface of all functions in this family is
100
.Fn wait6
101
which is otherwise very much like
102
.Fn wait4
103
but with a few very important distinctions.
104
.br
105
It will not wait for existed processes unless the option flag 
106
.Dv WEXITED
107
is explicitly specified.
108
This allows for waiting for processes which have experienced other
109
status changes without having to handle also the exit status from
110
the terminated processes.
111
Another important difference is the additional fifth argument
112
which must be either 
113
.Dv NULL
114
or a pointer to a
115
.Fa siginfo_t
116
structure.
117
Additionally the old
118
.Fa pid_t
119
argument has been split into two separate
120
.Fa idtype_t
121
and
122
.Fa id_t .
123
.br
124
Allowing for the distinction in how the
125
PID or PGID
126
is passed to the routine, calling
127
.Fn wait6
128
with the bits
129
.Dv WEXITED
130
and
131
.Dv WTRAPPED
132
set in the
133
.Fa options
134
and with
135
.Fa infop
136
set to
137
.Dv NULL ,
138
is still functionally equivalent to calling
139
.Fn wait4 .
140
The separation of
141
.Fa idtype
142
and
143
.Fa id
144
arguments has the benefit, though, that many other types of
145
IDs can be supported as well in addition to PID and PGID.
146
.sp
147
Notice that
148
.Fn wait6
149
is not required by any standard nor is it common in other
150
operating systems.
151
It is simply a generalized API to support in one function call
152
interface any and all of the functionality available through 
153
any of the other
154
.Fn wait*
155
functions.
156
Do not use it unless you fully accept the implied
157
limitations to the portability of your code.
158
.Pp
92
The
159
The
160
.Fa idtype
161
and
162
.Fa id
163
arguments specify which processes
164
.Fn waitid
165
and
166
.Fn wait6
167
shall wait for.
168
.Bl -bullet -offset indent
169
.It
170
If
171
.Fa idtype
172
is 
173
.Dv P_PID ,
174
.Fn waitid
175
and
176
.Fn wait6
177
wait for the child process with a process ID equal to
178
.Dv (pid_t)id .
179
.It
180
If
181
.Fa idtype
182
is 
183
.Dv P_PGID ,
184
.Fn waitid
185
and
186
.Fn wait6
187
wait for the child process with a process group ID equal to
188
.Dv (pid_t)id .
189
.It
190
If
191
.Fa idtype
192
is 
193
.Dv P_ALL ,
194
.Fn waitid
195
and
196
.Fn wait6
197
wait for any child process and the
198
.Dv id
199
is ignored.
200
.It
201
If
202
.Fa idtype
203
is 
204
.Dv P_PID
205
or
206
.Dv P_PGID
207
and the
208
.Dv id
209
is zero,
210
.Fn waitid
211
and
212
.Fn wait6
213
wait for any child process in the same process group as the caller.
214
.It
215
While no standard actually requires such functionality,
216
this implementation supports also other types of IDs to wait.
217
.br
218
Notice anyhow that using any of these non-standard features will
219
most likely seriously degrade the portability of your code.
220
Consider such use only as enabling technology for new creative
221
experimentation locked into its original environment.
222
.br
223
Use
224
.Fa idtype
225
value
226
.Dv P_UID
227
to filter processes based on their effective UID,
228
.Dv P_GID
229
to filter processes based on their effective GID.
230
.br
231
.Dv P_SID
232
could be used to filter based on the session ID.
233
In case the child process started its own new session,
234
SID will be the same as its own PID.
235
Otherwise the SID of a child process will match the caller's SID.
236
.br
237
.Dv P_ZONEID
238
facilitates waiting for processes within a certain jail.
239
.br
240
There could be still more meaningful ID types to wait for
241
like
242
.Dv P_PSETID
243
for processes restricted to a certain set of CPUs,
244
.Dv P_CID
245
to wait for processes in a certain scheduling class or
246
.Dv P_CPUID
247
to wait for processes nailed to a certain CPU.
248
These three
249
have not been implemented at the time of this writing,
250
because the data stored in the thread structures seems
251
to be zeroed when a process terminates before the parent
252
gets to wait for the zombie.
253
They are mentioned here as potentially useful extensions.
254
.El
255
.Pp
256
For all the other
257
.Fn wait*
258
variants the
93
.Fa wpid
259
.Fa wpid
94
argument specifies the set of child processes for which to wait.
260
argument specifies the set of child processes for which to wait.
261
.Bl -bullet -offset indent
262
.It
95
If
263
If
96
.Fa wpid
264
.Fa wpid
97
is -1, the call waits for any child process.
265
is -1, the call waits for any child process.
266
.It
98
If
267
If
99
.Fa wpid
268
.Fa wpid
100
is 0,
269
is 0,
101
the call waits for any child process in the process group of the caller.
270
the call waits for any child process in the process group of the caller.
271
.It
102
If
272
If
103
.Fa wpid
273
.Fa wpid
104
is greater than zero, the call waits for the process with process id
274
is greater than zero, the call waits for the process with process id
105
.Fa wpid .
275
.Fa wpid .
276
.It
106
If
277
If
107
.Fa wpid
278
.Fa wpid
108
is less than -1, the call waits for any process whose process group id
279
is less than -1, the call waits for any process whose process group id
109
equals the absolute value of
280
equals the absolute value of
110
.Fa wpid .
281
.Fa wpid .
282
.El
111
.Pp
283
.Pp
112
The
284
The
113
.Fa status
285
.Fa status
Lines 116-156 Link Here
116
The
288
The
117
.Fa options
289
.Fa options
118
argument contains the bitwise OR of any of the following options.
290
argument contains the bitwise OR of any of the following options.
119
The
291
.Bl -tag -width Ds
120
.Dv WCONTINUED
292
.It Dv WCONTINUED
121
option indicates that children of the current process that
293
indicates that children of the current process that
122
have continued from a job control stop, by receiving a
294
have continued from a job control stop, by receiving a
123
.Dv SIGCONT
295
.Dv SIGCONT
124
signal, should also have their status reported.
296
signal, should also have their status reported.
125
The
297
.It Dv WNOHANG
126
.Dv WNOHANG
298
is used to indicate that the call should not block when
127
option
299
there are no processes wishing to report status.
128
is used to indicate that the call should not block if
300
.It Dv WUNTRACED
129
there are no processes that wish to report status.
301
indicates that children of the current process which are stopped
130
If the
131
.Dv WUNTRACED
132
option is set,
133
children of the current process that are stopped
134
due to a
302
due to a
135
.Dv SIGTTIN , SIGTTOU , SIGTSTP ,
303
.Dv SIGTTIN , SIGTTOU , SIGTSTP ,
136
or
304
or
137
.Dv SIGSTOP
305
.Dv SIGSTOP
138
signal also have their status reported.
306
signal shall have their status reported.
139
The
307
.It Dv WSTOPPED
140
.Dv WSTOPPED
308
is an alias for
141
option is an alias for
142
.Dv WUNTRACED .
309
.Dv WUNTRACED .
143
The
310
.It Dv WTRAPPED
144
.Dv WNOWAIT
311
allows waiting for processes which have trapped or reached a breakpoint.
145
option keeps the process whose status is returned in a waitable state.
312
.It Dv WEXITED
313
indicates that the caller is wants to receive status reports from
314
terminated processes.
315
.br
316
This bit is implicitly set for the older functions
317
.Fn wait ,
318
.Fn waitpid ,
319
.Fn wait3 ,
320
and
321
.Fn wait4 
322
to avoid changing their traditional functionality.
323
.br
324
For the more recent APIs 
325
.Fn waitid
326
and
327
.Fn wait6
328
this bit has to be explicitly included in the 
329
.Fa options ,
330
if status reports from terminated processes are expected.
331
.br
332
This has the benefit that while using the latter two APIs
333
it is possible to request status reports only for processes
334
which have experienced some other status change, but which
335
have not terminated.
336
So, it is possible to avoid receiving reports for terminated
337
processes, in those parts of a program which are not able
338
to properly handle zombies and delay zombie processing to
339
other parts which can handle them properly.
340
.It Dv WNOWAIT
341
keeps the process whose status is returned in a waitable state.
146
The process may be waited for again after this call completes.
342
The process may be waited for again after this call completes.
343
.El
344
.sp
345
For the more recent APIs 
346
.Fn waitid
347
and
348
.Fn wait6
349
at least one of the options
350
.Dv WEXITED ,
351
.Dv WUNTRACED ,
352
.Dv WSTOPPED ,
353
.Dv WTRAPPED ,
354
or
355
.Dv WCONTINUED
356
must be specified.
357
Otherwise there will be no events for the call to report.
358
To avoid hanging indefinitely in such a case these functions currently
359
return -1 with errno set to
360
.Dv EINVAL .
147
.Pp
361
.Pp
148
If
362
If
149
.Fa rusage
363
.Fa rusage
150
is non-zero, a summary of the resources used by the terminated
364
is non-zero, a summary of the resources used by the terminated
151
process and all its
365
process and all its
152
children is returned (this information is currently not available
366
children is returned.
153
for stopped or continued processes).
367
.Pp
368
If
369
.Fa infop
370
is non-null, it must point to a 
371
.Dv siginfo_t
372
structure which will be filled such that the
373
.Dv si_signo
374
field will always be
375
.Dv SIGCHLD
376
and the field
377
.Dv si_pid
378
will be non-zero, if there is a status change to report.
379
If there are no status changes to report and WNOHANG is applied,
380
both of these fields will be zero.
381
.br
382
When using the
383
.Fn waitid
384
API with the
385
.Dv WNOHANG
386
option set checking these fields is the only way to know whether
387
there were any status changes to report, because the return value
388
from
389
.Fn waitid
390
will be zero as it is for any successful return from
391
.Fn waitid .
154
.Pp
392
.Pp
155
When the
393
When the
156
.Dv WNOHANG
394
.Dv WNOHANG
Lines 306-311 Link Here
306
is returned and
544
is returned and
307
.Va errno
545
.Va errno
308
is set to indicate the error.
546
is set to indicate the error.
547
.Pp
548
If
549
.Fn waitid
550
returns because one or more processes have a state change to report,
551
0 is returned.
552
To indicate an error, -1 will be returned and
553
.Dv errno
554
set to an appropriate value.
555
If
556
.Dv WNOHANG
557
was used, 0 can be returned indicating no error, but no processes
558
may have changed state either, if si_signo and/or si_pid are zero.
309
.Sh ERRORS
559
.Sh ERRORS
310
The
560
The
311
.Fn wait
561
.Fn wait
Lines 335-340 Link Here
335
or the signal did not have the
585
or the signal did not have the
336
.Dv SA_RESTART
586
.Dv SA_RESTART
337
flag set.
587
flag set.
588
.It Bq Er EINVAL
589
An invalid value was specified for
590
.Fa options ,
591
or
592
.Fa idtype
593
and
594
.Fa id
595
do not specify a valid set of processes.
338
.El
596
.El
339
.Sh SEE ALSO
597
.Sh SEE ALSO
340
.Xr _exit 2 ,
598
.Xr _exit 2 ,
(-)sys/kern/kern_exit.c (-30 / +334 lines)
Lines 674-679 Link Here
674
	int error, status;
674
	int error, status;
675
675
676
	error = kern_wait(td, WAIT_ANY, &status, 0, NULL);
676
	error = kern_wait(td, WAIT_ANY, &status, 0, NULL);
677
677
	if (error == 0)
678
	if (error == 0)
678
		td->td_retval[1] = status;
679
		td->td_retval[1] = status;
679
	return (error);
680
	return (error);
Lines 684-690 Link Here
684
 * The dirty work is handled by kern_wait().
685
 * The dirty work is handled by kern_wait().
685
 */
686
 */
686
int
687
int
687
sys_wait4(struct thread *td, struct wait_args *uap)
688
sys_wait4(struct thread *td, struct wait4_args *uap)
688
{
689
{
689
	struct rusage ru, *rup;
690
	struct rusage ru, *rup;
690
	int error, status;
691
	int error, status;
Lines 693-703 Link Here
693
		rup = &ru;
694
		rup = &ru;
694
	else
695
	else
695
		rup = NULL;
696
		rup = NULL;
697
696
	error = kern_wait(td, uap->pid, &status, uap->options, rup);
698
	error = kern_wait(td, uap->pid, &status, uap->options, rup);
699
700
	if (uap->status != NULL && error == 0)
701
		error = copyout(&status, uap->status, sizeof(status));
702
	if (uap->rusage != NULL && error == 0)
703
		error = copyout(&ru, uap->rusage, sizeof(struct rusage));
704
	return (error);
705
}
706
707
int
708
sys_wait6(struct thread *td, struct wait6_args *uap)
709
{
710
	struct rusage ru, *rup;
711
	siginfo_t  si, *sip;
712
	int error, status;
713
	idtype_t idtype;
714
	id_t id;
715
716
	idtype = uap->idtype;
717
	id = uap->id;
718
719
	if (uap->rusage != NULL)
720
		rup = &ru;
721
	else
722
		rup = NULL;
723
724
	if (uap->info != NULL)
725
		sip = &si;
726
	else
727
		sip = NULL;
728
729
	/*
730
	 *  We expect all callers of wait6()
731
	 *  to know about WEXITED and WTRAPPED!
732
	 */
733
	error = kern_wait6(td, idtype, id, &status, uap->options, rup, sip);
734
697
	if (uap->status != NULL && error == 0)
735
	if (uap->status != NULL && error == 0)
698
		error = copyout(&status, uap->status, sizeof(status));
736
		error = copyout(&status, uap->status, sizeof(status));
699
	if (uap->rusage != NULL && error == 0)
737
	if (uap->rusage != NULL && error == 0)
700
		error = copyout(&ru, uap->rusage, sizeof(struct rusage));
738
		error = copyout(&ru, uap->rusage, sizeof(struct rusage));
739
	if (uap->info != NULL && error == 0)
740
		error = copyout(&si, uap->info, sizeof(siginfo_t));
701
	return (error);
741
	return (error);
702
}
742
}
703
743
Lines 707-714 Link Here
707
 * lock as part of its work.
747
 * lock as part of its work.
708
 */
748
 */
709
void
749
void
710
proc_reap(struct thread *td, struct proc *p, int *status, int options,
750
proc_reap(struct thread *td, struct proc *p, int *status, int options)
711
    struct rusage *rusage)
712
{
751
{
713
	struct proc *q, *t;
752
	struct proc *q, *t;
714
753
Lines 718-727 Link Here
718
	KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
757
	KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
719
758
720
	q = td->td_proc;
759
	q = td->td_proc;
721
	if (rusage) {
760
722
		*rusage = p->p_ru;
723
		calcru(p, &rusage->ru_utime, &rusage->ru_stime);
724
	}
725
	PROC_SUNLOCK(p);
761
	PROC_SUNLOCK(p);
726
	td->td_retval[0] = p->p_pid;
762
	td->td_retval[0] = p->p_pid;
727
	if (status)
763
	if (status)
Lines 834-841 Link Here
834
}
870
}
835
871
836
static int
872
static int
837
proc_to_reap(struct thread *td, struct proc *p, pid_t pid, int *status,
873
proc_to_reap(struct thread *td, struct proc *p,
838
    int options, struct rusage *rusage)
874
	     idtype_t idtype, id_t id, 
875
	     int *status, int options,
876
	     struct rusage *rusage, siginfo_t *siginfo)
839
{
877
{
840
	struct proc *q;
878
	struct proc *q;
841
879
Lines 843-857 Link Here
843
881
844
	q = td->td_proc;
882
	q = td->td_proc;
845
	PROC_LOCK(p);
883
	PROC_LOCK(p);
846
	if (pid != WAIT_ANY && p->p_pid != pid && p->p_pgid != -pid) {
884
885
	switch (idtype) {
886
	case	P_ALL:
887
		break;
888
889
	case	P_PID:
890
		if (p->p_pid != (pid_t) id) {
891
			PROC_UNLOCK(p);
892
			return (0);
893
		}
894
		break;
895
896
	case	P_PGID:
897
		if (p->p_pgid != (pid_t) id) {
898
			PROC_UNLOCK(p);
899
			return (0);
900
		}
901
		break;
902
903
	case	P_SID:
904
		if (p->p_session->s_sid != (pid_t) id) {
905
			PROC_UNLOCK(p);
906
			return (0);
907
		}
908
		break;
909
910
	case	P_UID:
911
		if (p->p_ucred->cr_uid != (uid_t) id) {
912
			PROC_UNLOCK(p);
913
			return (0);
914
		}
915
		break;
916
917
	case	P_GID:
918
		if (p->p_ucred->cr_gid != (gid_t) id) {
919
			PROC_UNLOCK(p);
920
			return (0);
921
		}
922
		break;
923
924
	case	P_ZONEID:	/* jail */
925
		if (! p->p_ucred->cr_prison ||
926
		    (p->p_ucred->cr_prison->pr_id != (int) id)) {
927
			PROC_UNLOCK(p);
928
			return (0);
929
		}
930
		break;
931
932
#if 0
933
		/*
934
		 * It seems that the thread structures get zeroed out
935
		 * at process exit.
936
		 * This makes toast of all useful info related to
937
		 * CPU, CPU set, and scheduling priority class.
938
		 */
939
940
	case	P_PSETID:
941
		{
942
			struct thread	*td1;
943
944
			td1 = FIRST_THREAD_IN_PROC(p);
945
			if (td1->td_cpuset->cs_id != (cpusetid_t) id) {
946
				PROC_UNLOCK(p);
947
				return (0);
948
			}
949
		}
950
		break;
951
952
	case	P_CID:
953
		{
954
			struct thread	*td1;
955
956
			td1 = FIRST_THREAD_IN_PROC(p);
957
			if (td1->td_pri_class != (unsigned) id) {
958
				PROC_UNLOCK(p);
959
				return (0);
960
			}
961
		}
962
		break;
963
964
965
		/*
966
		 * Is there a good place for this?
967
		 * Supposedly also zeroed before it can be used, right?
968
		 */
969
970
	case	P_CPUID:
971
		{
972
			struct thread	*td1;
973
974
			td1 = FIRST_THREAD_IN_PROC(p);
975
			if (td1->td_lastcpu != (unsigned) id) {
976
				PROC_UNLOCK(p);
977
				return (0);
978
			}
979
		}
980
		break;
981
#endif
982
983
	default:
847
		PROC_UNLOCK(p);
984
		PROC_UNLOCK(p);
848
		return (0);
985
		return (0);
986
		break;
849
	}
987
	}
988
850
	if (p_canwait(td, p)) {
989
	if (p_canwait(td, p)) {
851
		PROC_UNLOCK(p);
990
		PROC_UNLOCK(p);
852
		return (0);
991
		return (0);
853
	}
992
	}
854
993
994
	if (((options & WEXITED) == 0) && (p->p_state == PRS_ZOMBIE)) {
995
		PROC_UNLOCK(p);
996
		return (0);
997
	}
998
		
855
	/*
999
	/*
856
	 * This special case handles a kthread spawned by linux_clone
1000
	 * This special case handles a kthread spawned by linux_clone
857
	 * (see linux_misc.c).  The linux_wait4 and linux_waitpid
1001
	 * (see linux_misc.c).  The linux_wait4 and linux_waitpid
Lines 867-874 Link Here
867
	}
1011
	}
868
1012
869
	PROC_SLOCK(p);
1013
	PROC_SLOCK(p);
1014
1015
	/* New siginfo stuff... */
1016
1017
	if (siginfo) {
1018
		bzero (siginfo, sizeof (*siginfo));
1019
		siginfo->si_signo = SIGCHLD;
1020
		siginfo->si_errno = 0;
1021
1022
		/*
1023
		 *  Right, this is still a rough estimate.
1024
		 *  We will fix the cases TRAPPED, STOPPED,
1025
		 *  and CONTINUED later.
1026
		 */
1027
1028
		if (WCOREDUMP(p->p_xstat))
1029
			siginfo->si_code = CLD_DUMPED;
1030
		else if (WIFSIGNALED(p->p_xstat))
1031
			siginfo->si_code = CLD_KILLED;
1032
		else
1033
			siginfo->si_code = CLD_EXITED;
1034
1035
		siginfo->si_pid = p->p_pid;
1036
		siginfo->si_uid = p->p_ucred->cr_uid;
1037
		siginfo->si_status = p->p_xstat;
1038
1039
		/*
1040
		 *  The si_addr field would be useful
1041
		 *  additional detail, but apparently
1042
		 *  the PC value may be lost when we
1043
		 *  reach this point.
1044
		 */
1045
		siginfo->si_addr = NULL;	/* XXX */
1046
	}
1047
1048
	/*
1049
	 * There should be no reason to limit resources usage info
1050
	 * to exited processes only.
1051
	 * A snapshot about any resources used by a stopped process
1052
	 * may be exactly what is needed.
1053
	 * (1) Solaris limits available info to times only.
1054
	 * (2) Linux does not declare any limitations.
1055
	 * (3) Now within the same PROC_SLOCK anyway.
1056
	 */
1057
1058
	if (rusage) {
1059
		*rusage = p->p_ru;
1060
		calcru(p, &rusage->ru_utime, &rusage->ru_stime);
1061
	}
1062
870
	if (p->p_state == PRS_ZOMBIE) {
1063
	if (p->p_state == PRS_ZOMBIE) {
871
		proc_reap(td, p, status, options, rusage);
1064
		proc_reap(td, p, status, options);
872
		return (-1);
1065
		return (-1);
873
	}
1066
	}
874
	PROC_SUNLOCK(p);
1067
	PROC_SUNLOCK(p);
Lines 877-900 Link Here
877
}
1070
}
878
1071
879
int
1072
int
880
kern_wait(struct thread *td, pid_t pid, int *status, int options,
1073
kern_wait(struct thread *td, pid_t pid,
881
    struct rusage *rusage)
1074
	  int *status, int options, struct rusage *rusage)
1075
{
1076
	idtype_t idtype;
1077
	id_t id;
1078
1079
	if (pid == WAIT_ANY) {
1080
		idtype = P_ALL;
1081
		id = 0;
1082
	}
1083
	else if (pid <= 0) {
1084
		idtype = P_PGID;
1085
		id = (id_t) -pid;
1086
	}
1087
	else {
1088
		idtype = P_PID;
1089
		id = (id_t) pid;
1090
	}
1091
1092
	/*
1093
	 *  For backward compatibility we implicitly
1094
	 *  add flags WEXITED and WTRAPPED here.
1095
	 */
1096
1097
	options |= (WEXITED | WTRAPPED);
1098
1099
	return (kern_wait6 (td, idtype, id, status, options, rusage, NULL));
1100
}
1101
1102
int
1103
kern_wait6(struct thread *td, idtype_t idtype, id_t id,
1104
	   int *status, int options,
1105
	   struct rusage *rusage, siginfo_t *siginfo)
882
{
1106
{
883
	struct proc *p, *q;
1107
	struct proc *p, *q;
884
	int error, nfound, ret;
1108
	int error, nfound, ret;
885
1109
886
	AUDIT_ARG_PID(pid);
1110
#if 0
1111
	AUDIT_ARG_VALUE((int) idtype);	/* XXX - This is likely wrong! */
1112
#endif
1113
	AUDIT_ARG_PID((pid_t) id);	/* XXX - This may be wrong! */
887
	AUDIT_ARG_VALUE(options);
1114
	AUDIT_ARG_VALUE(options);
888
1115
889
	q = td->td_proc;
1116
	q = td->td_proc;
890
	if (pid == 0) {
1117
1118
	if (((pid_t) id == WAIT_MYPGRP) &&
1119
	    ((idtype == P_PID) || (idtype == P_PGID))) {
891
		PROC_LOCK(q);
1120
		PROC_LOCK(q);
892
		pid = -q->p_pgid;
1121
		id = (id_t) q->p_pgid;
893
		PROC_UNLOCK(q);
1122
		PROC_UNLOCK(q);
1123
		idtype = P_PGID;
894
	}
1124
	}
1125
895
	/* If we don't know the option, just return. */
1126
	/* If we don't know the option, just return. */
896
	if (options & ~(WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WLINUXCLONE))
1127
	if (options & ~(WUNTRACED|WNOHANG|WCONTINUED|WNOWAIT|WEXITED|WTRAPPED|WLINUXCLONE))
897
		return (EINVAL);
1128
		return (EINVAL);
1129
1130
	if ((options & (WEXITED|WUNTRACED|WCONTINUED|WTRAPPED)) == 0) {
1131
		/*
1132
		 *  We will be unable to find any matching processes,
1133
		 *  because there are no known events to look for.
1134
		 *  So, to tell the programmer (s)he is doing something
1135
		 *  patently dysfunctional, we return EINVAL.
1136
		 */
1137
		if (siginfo)
1138
			bzero (siginfo, sizeof (*siginfo));
1139
		td->td_retval[0] = -1;
1140
		return (EINVAL);
1141
	}
1142
898
loop:
1143
loop:
899
	if (q->p_flag & P_STATCHILD) {
1144
	if (q->p_flag & P_STATCHILD) {
900
		PROC_LOCK(q);
1145
		PROC_LOCK(q);
Lines 904-910 Link Here
904
	nfound = 0;
1149
	nfound = 0;
905
	sx_xlock(&proctree_lock);
1150
	sx_xlock(&proctree_lock);
906
	LIST_FOREACH(p, &q->p_children, p_sibling) {
1151
	LIST_FOREACH(p, &q->p_children, p_sibling) {
907
		ret = proc_to_reap(td, p, pid, status, options, rusage);
1152
		ret = proc_to_reap(td, p, idtype, id,
1153
				   status, options, rusage, siginfo);
908
		if (ret == 0)
1154
		if (ret == 0)
909
			continue;
1155
			continue;
910
		else if (ret == 1)
1156
		else if (ret == 1)
Lines 914-933 Link Here
914
1160
915
		PROC_LOCK(p);
1161
		PROC_LOCK(p);
916
		PROC_SLOCK(p);
1162
		PROC_SLOCK(p);
917
		if ((p->p_flag & P_STOPPED_SIG) &&
1163
1164
		if ((options & WTRAPPED) &&
1165
		    (p->p_flag & P_TRACED) &&
1166
		    (p->p_flag & (P_STOPPED_TRACE | P_STOPPED_SIG)) &&
918
		    (p->p_suspcount == p->p_numthreads) &&
1167
		    (p->p_suspcount == p->p_numthreads) &&
919
		    (p->p_flag & P_WAITED) == 0 &&
1168
		    ((p->p_flag & P_WAITED) == 0)) {
920
		    (p->p_flag & P_TRACED || options & WUNTRACED)) {
921
			PROC_SUNLOCK(p);
1169
			PROC_SUNLOCK(p);
922
			p->p_flag |= P_WAITED;
1170
1171
			if ((options & WNOWAIT) == 0)
1172
				p->p_flag |= P_WAITED;
1173
923
			sx_xunlock(&proctree_lock);
1174
			sx_xunlock(&proctree_lock);
924
			td->td_retval[0] = p->p_pid;
1175
			td->td_retval[0] = p->p_pid;
1176
925
			if (status)
1177
			if (status)
926
				*status = W_STOPCODE(p->p_xstat);
1178
				*status = W_STOPCODE(p->p_xstat);
927
1179
928
			PROC_LOCK(q);
1180
			if (siginfo) {
929
			sigqueue_take(p->p_ksi);
1181
				siginfo->si_status = W_STOPCODE(p->p_xstat);
930
			PROC_UNLOCK(q);
1182
				siginfo->si_code = CLD_TRAPPED;
1183
			}
1184
1185
			if ((options & WNOWAIT) == 0) {
1186
				PROC_LOCK(q);
1187
				sigqueue_take(p->p_ksi);
1188
				PROC_UNLOCK(q);
1189
			}
1190
1191
			PROC_UNLOCK(p);
1192
1193
			return (0);
1194
		}
1195
1196
		if ((options & WUNTRACED) &&
1197
		    (p->p_flag & P_STOPPED_SIG) &&
1198
		    (p->p_suspcount == p->p_numthreads) &&
1199
		    ((p->p_flag & P_WAITED) == 0)) {
1200
			PROC_SUNLOCK(p);
1201
1202
			if ((options & WNOWAIT) == 0)
1203
				p->p_flag |= P_WAITED;
1204
1205
			sx_xunlock(&proctree_lock);
1206
			td->td_retval[0] = p->p_pid;
1207
1208
			if (status)
1209
				*status = W_STOPCODE(p->p_xstat);
1210
1211
			if (siginfo) {
1212
				siginfo->si_status = W_STOPCODE(p->p_xstat);
1213
				siginfo->si_code = CLD_STOPPED;
1214
			}
1215
1216
			if ((options & WNOWAIT) == 0) {
1217
				PROC_LOCK(q);
1218
				sigqueue_take(p->p_ksi);
1219
				PROC_UNLOCK(q);
1220
			}
1221
931
			PROC_UNLOCK(p);
1222
			PROC_UNLOCK(p);
932
1223
933
			return (0);
1224
			return (0);
Lines 936-950 Link Here
936
		if (options & WCONTINUED && (p->p_flag & P_CONTINUED)) {
1227
		if (options & WCONTINUED && (p->p_flag & P_CONTINUED)) {
937
			sx_xunlock(&proctree_lock);
1228
			sx_xunlock(&proctree_lock);
938
			td->td_retval[0] = p->p_pid;
1229
			td->td_retval[0] = p->p_pid;
939
			p->p_flag &= ~P_CONTINUED;
940
1230
941
			PROC_LOCK(q);
1231
			if ((options & WNOWAIT) == 0) {
942
			sigqueue_take(p->p_ksi);
1232
				p->p_flag &= ~P_CONTINUED;
943
			PROC_UNLOCK(q);
1233
1234
				PROC_LOCK(q);
1235
				sigqueue_take(p->p_ksi);
1236
				PROC_UNLOCK(q);
1237
			}
1238
944
			PROC_UNLOCK(p);
1239
			PROC_UNLOCK(p);
945
1240
946
			if (status)
1241
			if (status)
947
				*status = SIGCONT;
1242
				*status = SIGCONT;
1243
1244
			if (siginfo) {
1245
				siginfo->si_status = SIGCONT;
1246
				siginfo->si_code = CLD_CONTINUED;
1247
			}
1248
948
			return (0);
1249
			return (0);
949
		}
1250
		}
950
		PROC_UNLOCK(p);
1251
		PROC_UNLOCK(p);
Lines 963-969 Link Here
963
	 * to successfully wait until the child becomes a zombie.
1264
	 * to successfully wait until the child becomes a zombie.
964
	 */
1265
	 */
965
	LIST_FOREACH(p, &q->p_orphans, p_orphan) {
1266
	LIST_FOREACH(p, &q->p_orphans, p_orphan) {
966
		ret = proc_to_reap(td, p, pid, status, options, rusage);
1267
		ret = proc_to_reap(td, p, idtype, id,
1268
				   status, options, rusage, siginfo);
967
		if (ret == 0)
1269
		if (ret == 0)
968
			continue;
1270
			continue;
969
		else if (ret == 1)
1271
		else if (ret == 1)
Lines 977-982 Link Here
977
	}
1279
	}
978
	if (options & WNOHANG) {
1280
	if (options & WNOHANG) {
979
		sx_xunlock(&proctree_lock);
1281
		sx_xunlock(&proctree_lock);
1282
		if (siginfo)
1283
			bzero (siginfo, sizeof (*siginfo));
980
		td->td_retval[0] = 0;
1284
		td->td_retval[0] = 0;
981
		return (0);
1285
		return (0);
982
	}
1286
	}
(-)lib/libc/sys/Makefile.inc (-1 / +1 lines)
Lines 210-214 Link Here
210
MLINKS+=truncate.2 ftruncate.2
210
MLINKS+=truncate.2 ftruncate.2
211
MLINKS+=unlink.2 unlinkat.2
211
MLINKS+=unlink.2 unlinkat.2
212
MLINKS+=utimes.2 futimes.2 utimes.2 futimesat.2 utimes.2 lutimes.2
212
MLINKS+=utimes.2 futimes.2 utimes.2 futimesat.2 utimes.2 lutimes.2
213
MLINKS+=wait.2 wait3.2 wait.2 wait4.2 wait.2 waitpid.2
213
MLINKS+=wait.2 wait3.2 wait.2 wait4.2 wait.2 waitpid.2 wait.2 waitid.2 wait.2 wait6.2
214
MLINKS+=write.2 pwrite.2 write.2 pwritev.2 write.2 writev.2
214
MLINKS+=write.2 pwrite.2 write.2 pwritev.2 write.2 writev.2
(-)lib/libc/gen/waitid.c (+57 lines)
Added Link Here
1
2
#include "namespace.h"
3
#include <sys/types.h>
4
#include <sys/wait.h>
5
#include <stddef.h>
6
#include <string.h>
7
#include <signal.h>
8
#include <errno.h>
9
#include "un-namespace.h"
10
11
int
12
__waitid (idtype, id, info, flags)
13
    idtype_t	idtype;
14
    id_t	id;
15
    siginfo_t	*info;
16
    int		flags;
17
{
18
    int	    status;
19
    pid_t   ret;
20
21
    /* 
22
     *	NOTICE!
23
     *	The traditional PID/PGID == 0 to wait for
24
     *	any process in the caller's own process group
25
     *	still works when the idtype is set to either
26
     *	P_PID or P_PGID.
27
     */
28
29
    if (info) {
30
	memset (info, '\0', sizeof (*info));
31
    }
32
33
    /*
34
     *	In case you wish to start waiting for any
35
     *	processes
36
     *	- running in a certain jail (zone),
37
     *	- running on a certain cpu, or
38
     *	- nailed to a certain CPU set,
39
     *	- etc.
40
     *  you will have to extend the kern_wait6() in
41
     *  the kernel to support such idtype_t flavours.
42
     */
43
44
    ret = _wait6 (idtype, id, &status, flags, NULL, info);
45
46
    if (ret < 0) {
47
	ret = -1;
48
    }
49
    else {
50
	ret = 0;
51
    }
52
53
    return ((int) ret);
54
}
55
56
__weak_reference(__waitid, waitid);
57
__weak_reference(__waitid, _waitid);

Return to bug 170346