@@ -35,7 +35,9 @@ use crate::wordexp::{expand_word, expand_word_to_string, word_to_pattern};
3535use nix:: errno:: Errno ;
3636use nix:: libc;
3737use nix:: sys:: wait:: { WaitPidFlag , WaitStatus } ;
38- use nix:: unistd:: { getcwd, getpgrp, getpid, getppid, setpgid, ForkResult , Pid } ;
38+ use nix:: unistd:: {
39+ getcwd, getgid, getpgid, getpgrp, getpid, getppid, setpgid, tcsetpgrp, ForkResult , Pid ,
40+ } ;
3941use std:: collections:: HashMap ;
4042use std:: ffi:: { CString , OsString } ;
4143use std:: fmt:: { Display , Formatter } ;
@@ -729,17 +731,17 @@ impl Shell {
729731 match fork ( ) ? {
730732 ForkResult :: Child => {
731733 self . become_subshell ( ) ;
732- setpgid ( Pid :: from_raw ( 0 ) , Pid :: from_raw ( 0 ) )
733- . expect ( "failed to create new process group for pipeline" ) ;
734+ // this should never fail as both arguments are valid
735+ setpgid ( Pid :: from_raw ( 0 ) , Pid :: from_raw ( 0 ) ) . unwrap ( ) ;
734736 let pipeline_pgid = getpgrp ( ) ;
735737
736738 let mut current_stdin = libc:: STDIN_FILENO ;
737739 for command in pipeline. commands . head ( ) {
738740 let ( read_pipe, write_pipe) = pipe ( ) ?;
739741 match fork ( ) ? {
740742 ForkResult :: Child => {
741- setpgid ( Pid :: from_raw ( 0 ) , pipeline_pgid)
742- . expect ( "failed to set pipeline pgid" ) ;
743+ // should never fail as ` pipeline_pgid` is a valid process group
744+ setpgid ( Pid :: from_raw ( 0 ) , pipeline_pgid ) . unwrap ( ) ;
743745 drop ( read_pipe) ;
744746 dup2 ( current_stdin, libc:: STDIN_FILENO ) ?;
745747 dup2 ( write_pipe. as_raw_fd ( ) , libc:: STDOUT_FILENO ) ?;
@@ -764,9 +766,20 @@ impl Shell {
764766 }
765767 ForkResult :: Parent { child } => {
766768 if is_process_in_foreground ( ) {
767- nix:: unistd:: tcsetpgrp ( io:: stdin ( ) . as_fd ( ) , child) . unwrap ( ) ;
769+ // unwrap should never fail as child is a valid process id and in the
770+ // same session as the shell process
771+ while getpgid ( Some ( child) ) . unwrap ( ) . as_raw ( ) as u32 == getgid ( ) . as_raw ( ) {
772+ // loop until child is process group leader
773+ self . update_global_state ( ) ;
774+ std:: thread:: sleep ( Duration :: from_millis ( 16 ) ) ;
775+ }
776+ // should never fail as stdin is a valid file descriptor and
777+ // child is a valid group id and is in the same session
778+ // as the shell process
779+ tcsetpgrp ( io:: stdin ( ) . as_fd ( ) , child) . unwrap ( ) ;
768780 pipeline_exit_status = self . wait_child_process ( child) ?;
769- nix:: unistd:: tcsetpgrp ( io:: stdin ( ) . as_fd ( ) , getpgrp ( ) ) . unwrap ( ) ;
781+ // should never fail
782+ tcsetpgrp ( io:: stdin ( ) . as_fd ( ) , getpgrp ( ) ) . unwrap ( ) ;
770783 } else {
771784 pipeline_exit_status = self . wait_child_process ( child) ?;
772785 }
0 commit comments