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
470470int
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
512482loop :
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+
610697void
611698proc_finish_wait (struct proc * waiter , struct proc * p )
612699{
0 commit comments