Skip to content

Commit 8112871

Browse files
committed
Implement waitid(2) which is now part of POSIX and used by mozilla.
This includes a change of siginfo_r which is technically an ABI break but this should have no real-world impact since the members involved are never touched by the kernel. ok millert@, deraadt@
1 parent 68204e8 commit 8112871

File tree

3 files changed

+156
-51
lines changed

3 files changed

+156
-51
lines changed

sys/kern/kern_exit.c

Lines changed: 133 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: kern_exit.c,v 1.204 2022/08/14 01:58:27 jsg Exp $ */
1+
/* $OpenBSD: kern_exit.c,v 1.205 2022/10/25 16:08:26 kettenis Exp $ */
22
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
33

44
/*
@@ -468,68 +468,53 @@ reaper(void *arg)
468468
}
469469

470470
int
471-
sys_wait4(struct proc *q, void *v, register_t *retval)
472-
{
473-
struct sys_wait4_args /* {
474-
syscallarg(pid_t) pid;
475-
syscallarg(int *) status;
476-
syscallarg(int) options;
477-
syscallarg(struct rusage *) rusage;
478-
} */ *uap = v;
479-
struct rusage ru;
480-
int status, error;
481-
482-
error = dowait4(q, SCARG(uap, pid),
483-
SCARG(uap, status) ? &status : NULL,
484-
SCARG(uap, options), SCARG(uap, rusage) ? &ru : NULL, retval);
485-
if (error == 0 && retval[0] > 0 && SCARG(uap, status)) {
486-
error = copyout(&status, SCARG(uap, status), sizeof(status));
487-
}
488-
if (error == 0 && retval[0] > 0 && SCARG(uap, rusage)) {
489-
error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
490-
#ifdef KTRACE
491-
if (error == 0 && KTRPOINT(q, KTR_STRUCT))
492-
ktrrusage(q, &ru);
493-
#endif
494-
}
495-
return (error);
496-
}
497-
498-
int
499-
dowait4(struct proc *q, pid_t pid, int *statusp, int options,
500-
struct rusage *rusage, register_t *retval)
471+
dowait6(struct proc *q, idtype_t idtype, id_t id, int *statusp, int options,
472+
struct rusage *rusage, siginfo_t *info, register_t *retval)
501473
{
502474
int nfound;
503475
struct process *pr;
504476
struct proc *p;
505477
int error;
506478

507-
if (pid == 0)
508-
pid = -q->p_p->ps_pgid;
509-
if (options &~ (WUNTRACED|WNOHANG|WCONTINUED))
510-
return (EINVAL);
479+
if (info != NULL)
480+
memset(info, 0, sizeof(*info));
511481

512482
loop:
513483
nfound = 0;
514484
LIST_FOREACH(pr, &q->p_p->ps_children, ps_sibling) {
515485
if ((pr->ps_flags & PS_NOZOMBIE) ||
516-
(pid != WAIT_ANY &&
517-
pr->ps_pid != pid &&
518-
pr->ps_pgid != -pid))
486+
(idtype == P_PID && id != pr->ps_pid) ||
487+
(idtype == P_PGID && id != pr->ps_pgid))
519488
continue;
520489

521490
p = pr->ps_mainproc;
522491

523492
nfound++;
524-
if (pr->ps_flags & PS_ZOMBIE) {
493+
if ((options & WEXITED) && (pr->ps_flags & PS_ZOMBIE)) {
525494
retval[0] = pr->ps_pid;
495+
if (info != NULL) {
496+
info->si_pid = pr->ps_pid;
497+
info->si_uid = pr->ps_ucred->cr_uid;
498+
info->si_signo = SIGCHLD;
499+
if (pr->ps_xsig == 0) {
500+
info->si_code = CLD_EXITED;
501+
info->si_status = pr->ps_xexit;
502+
} else if (WCOREDUMP(pr->ps_xsig)) {
503+
info->si_code = CLD_DUMPED;
504+
info->si_status = _WSTATUS(pr->ps_xsig);
505+
} else {
506+
info->si_code = CLD_KILLED;
507+
info->si_status = _WSTATUS(pr->ps_xsig);
508+
}
509+
}
526510

527511
if (statusp != NULL)
528512
*statusp = W_EXITCODE(pr->ps_xexit,
529513
pr->ps_xsig);
530514
if (rusage != NULL)
531515
memcpy(rusage, pr->ps_ru, sizeof(*rusage));
532-
proc_finish_wait(q, p);
516+
if ((options & WNOWAIT) == 0)
517+
proc_finish_wait(q, p);
533518
return (0);
534519
}
535520
if (pr->ps_flags & PS_TRACED &&
@@ -539,8 +524,17 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options,
539524
if (single_thread_wait(pr, 0))
540525
goto loop;
541526

542-
atomic_setbits_int(&pr->ps_flags, PS_WAITED);
527+
if ((options & WNOWAIT) == 0)
528+
atomic_setbits_int(&pr->ps_flags, PS_WAITED);
529+
543530
retval[0] = pr->ps_pid;
531+
if (info != NULL) {
532+
info->si_pid = pr->ps_pid;
533+
info->si_uid = pr->ps_ucred->cr_uid;
534+
info->si_signo = SIGCHLD;
535+
info->si_code = CLD_TRAPPED;
536+
info->si_status = pr->ps_xsig;
537+
}
544538

545539
if (statusp != NULL)
546540
*statusp = W_STOPCODE(pr->ps_xsig);
@@ -553,8 +547,17 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options,
553547
(p->p_flag & P_SUSPSINGLE) == 0 &&
554548
(pr->ps_flags & PS_TRACED ||
555549
options & WUNTRACED)) {
556-
atomic_setbits_int(&pr->ps_flags, PS_WAITED);
550+
if ((options & WNOWAIT) == 0)
551+
atomic_setbits_int(&pr->ps_flags, PS_WAITED);
552+
557553
retval[0] = pr->ps_pid;
554+
if (info != 0) {
555+
info->si_pid = pr->ps_pid;
556+
info->si_uid = pr->ps_ucred->cr_uid;
557+
info->si_signo = SIGCHLD;
558+
info->si_code = CLD_STOPPED;
559+
info->si_status = pr->ps_xsig;
560+
}
558561

559562
if (statusp != NULL)
560563
*statusp = W_STOPCODE(pr->ps_xsig);
@@ -563,8 +566,17 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options,
563566
return (0);
564567
}
565568
if ((options & WCONTINUED) && (p->p_flag & P_CONTINUED)) {
566-
atomic_clearbits_int(&p->p_flag, P_CONTINUED);
569+
if ((options & WNOWAIT) == 0)
570+
atomic_clearbits_int(&p->p_flag, P_CONTINUED);
571+
567572
retval[0] = pr->ps_pid;
573+
if (info != NULL) {
574+
info->si_pid = pr->ps_pid;
575+
info->si_uid = pr->ps_ucred->cr_uid;
576+
info->si_signo = SIGCHLD;
577+
info->si_code = CLD_CONTINUED;
578+
info->si_status = SIGCONT;
579+
}
568580

569581
if (statusp != NULL)
570582
*statusp = _WCONTINUED;
@@ -588,9 +600,8 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options,
588600
if (nfound == 0) {
589601
LIST_FOREACH(pr, &q->p_p->ps_orphans, ps_orphan) {
590602
if ((pr->ps_flags & PS_NOZOMBIE) ||
591-
(pid != WAIT_ANY &&
592-
pr->ps_pid != pid &&
593-
pr->ps_pgid != -pid))
603+
(idtype == P_PID && id != pr->ps_pid) ||
604+
(idtype == P_PGID && id != pr->ps_pgid))
594605
continue;
595606
nfound++;
596607
break;
@@ -607,6 +618,82 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options,
607618
goto loop;
608619
}
609620

621+
int
622+
sys_wait4(struct proc *q, void *v, register_t *retval)
623+
{
624+
struct sys_wait4_args /* {
625+
syscallarg(pid_t) pid;
626+
syscallarg(int *) status;
627+
syscallarg(int) options;
628+
syscallarg(struct rusage *) rusage;
629+
} */ *uap = v;
630+
struct rusage ru;
631+
pid_t pid = SCARG(uap, pid);
632+
int options = SCARG(uap, options);
633+
int status, error;
634+
idtype_t idtype;
635+
id_t id;
636+
637+
if (SCARG(uap, options) &~ (WUNTRACED|WNOHANG|WCONTINUED))
638+
return (EINVAL);
639+
640+
if (SCARG(uap, pid) == WAIT_MYPGRP) {
641+
idtype = P_PGID;
642+
id = -q->p_p->ps_pgid;
643+
} else if (SCARG(uap, pid) == WAIT_ANY) {
644+
idtype = P_ALL;
645+
id = 0;
646+
} else {
647+
idtype = P_PID;
648+
id = pid;
649+
}
650+
651+
error = dowait6(q, idtype, id,
652+
SCARG(uap, status) ? &status : NULL, options | WEXITED,
653+
SCARG(uap, rusage) ? &ru : NULL, NULL, retval);
654+
if (error == 0 && retval[0] > 0 && SCARG(uap, status)) {
655+
error = copyout(&status, SCARG(uap, status), sizeof(status));
656+
}
657+
if (error == 0 && retval[0] > 0 && SCARG(uap, rusage)) {
658+
error = copyout(&ru, SCARG(uap, rusage), sizeof(ru));
659+
#ifdef KTRACE
660+
if (error == 0 && KTRPOINT(q, KTR_STRUCT))
661+
ktrrusage(q, &ru);
662+
#endif
663+
}
664+
return (error);
665+
}
666+
667+
int
668+
sys_waitid(struct proc *q, void *v, register_t *retval)
669+
{
670+
struct sys_waitid_args /* {
671+
syscallarg(idtype_t) idtype;
672+
syscallarg(id_t) id;
673+
syscallarg(siginfo_t) info;
674+
syscallarg(int) options;
675+
} */ *uap = v;
676+
siginfo_t info;
677+
idtype_t idtype = SCARG(uap, idtype);
678+
int options = SCARG(uap, options);
679+
int error;
680+
681+
if (options &~ (WSTOPPED|WCONTINUED|WEXITED|WNOHANG|WNOWAIT))
682+
return (EINVAL);
683+
if ((options & (WSTOPPED|WCONTINUED|WEXITED)) == 0)
684+
return (EINVAL);
685+
if (idtype != P_ALL && idtype != P_PID && idtype != P_PGID)
686+
return (EINVAL);
687+
688+
error = dowait6(q, idtype, SCARG(uap, id), NULL,
689+
options, NULL, &info, retval);
690+
if (error == 0)
691+
error = copyout(&info, SCARG(uap, info), sizeof(info));
692+
if (error == 0)
693+
retval[0] = 0;
694+
return (error);
695+
}
696+
610697
void
611698
proc_finish_wait(struct proc *waiter, struct proc *p)
612699
{

sys/sys/siginfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: siginfo.h,v 1.12 2017/04/07 04:48:44 guenther Exp $ */
1+
/* $OpenBSD: siginfo.h,v 1.13 2022/10/25 16:08:26 kettenis Exp $ */
22

33
/*
44
* Copyright (c) 1997 Theo de Raadt
@@ -137,9 +137,9 @@ typedef struct {
137137
int _pad[SI_PAD]; /* for future growth */
138138
struct { /* kill(), SIGCHLD */
139139
pid_t _pid; /* process ID */
140+
uid_t _uid;
140141
union {
141142
struct {
142-
uid_t _uid;
143143
union sigval _value;
144144
} _kill;
145145
struct {
@@ -173,11 +173,11 @@ typedef struct {
173173
} siginfo_t;
174174

175175
#define si_pid _data._proc._pid
176+
#define si_uid _data._proc._uid
176177

177178
#define si_status _data._proc._pdata._cld._status
178179
#define si_stime _data._proc._pdata._cld._stime
179180
#define si_utime _data._proc._pdata._cld._utime
180-
#define si_uid _data._proc._pdata._kill._uid
181181
#define si_value _data._proc._pdata._kill._value
182182
#define si_addr _data._fault._addr
183183
#define si_trapno _data._fault._trapno

sys/sys/wait.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: wait.h,v 1.18 2021/03/10 10:21:47 jsg Exp $ */
1+
/* $OpenBSD: wait.h,v 1.19 2022/10/25 16:08:26 kettenis Exp $ */
22
/* $NetBSD: wait.h,v 1.11 1996/04/09 20:55:51 cgd Exp $ */
33

44
/*
@@ -36,6 +36,7 @@
3636
#define _SYS_WAIT_H_
3737

3838
#include <sys/cdefs.h>
39+
#include <sys/siginfo.h>
3940

4041
/*
4142
* This file holds definitions relevant to the wait4 system call
@@ -71,11 +72,25 @@
7172
* indicates that the caller should receive status about untraced children
7273
* which stop due to signals. If children are stopped and a wait without
7374
* this option is done, it is as though they were still running... nothing
74-
* about them is returned.
75+
* about them is returned. WNOWAIT only requests information about zombie,
76+
* leaving the proc around, available for later waits.
7577
*/
7678
#define WNOHANG 1 /* don't hang in wait */
7779
#define WUNTRACED 2 /* tell about stopped, untraced children */
80+
#define WSTOPPED WUNTRACED
7881
#define WCONTINUED 8 /* report a job control continued process */
82+
#if __POSIX_VISIBLE >= 200809 || _XPG_VISIBLE
83+
#define WEXITED 4 /* wait for exited processes */
84+
#define WNOWAIT 16 /* poll only */
85+
#endif
86+
87+
#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE
88+
typedef enum {
89+
P_ALL,
90+
P_PGID,
91+
P_PID
92+
} idtype_t;
93+
#endif
7994

8095
#if __BSD_VISIBLE
8196
/*
@@ -93,6 +108,9 @@ struct rusage; /* forward declaration */
93108

94109
pid_t wait(int *);
95110
pid_t waitpid(pid_t, int *, int);
111+
#if __POSIX_VISIBLE >= 200809 || __XPG_VISIBLE
112+
int waitid(idtype_t, id_t, siginfo_t *, int);
113+
#endif
96114
#if __BSD_VISIBLE
97115
pid_t wait3(int *, int, struct rusage *);
98116
pid_t wait4(pid_t, int *, int, struct rusage *);

0 commit comments

Comments
 (0)