aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar axel <axel@liljencrantz.se>2006-08-27 10:52:52 +1000
committerGravatar axel <axel@liljencrantz.se>2006-08-27 10:52:52 +1000
commit1c86395ed8d2fff840293ba7c8332ef73a935032 (patch)
tree670fbe55a0d9c66b305f8621a3c4fdd1b1727e16
parent3c8d2a1126bfe97e1ba6839f725227b1fc232485 (diff)
Fix bug reportad by Martin Bähr that causes fish fail when using blocks in pipelines in interactive mode.
darcs-hash:20060827005252-ac50b-09c98537b9de72f0d4a2e5a28490b2e38fe321c8.gz
-rw-r--r--exec.c80
1 files changed, 71 insertions, 9 deletions
diff --git a/exec.c b/exec.c
index 25f8ead6..d500aecc 100644
--- a/exec.c
+++ b/exec.c
@@ -441,7 +441,9 @@ static void launch_process( process_t *p )
{
// debug( 1, L"exec '%ls'", p->argv[0] );
- execve (wcs2str(p->actual_cmd), wcsv2strv( (const wchar_t **) p->argv), env_export_arr( 0 ) );
+ execve ( wcs2str(p->actual_cmd),
+ wcsv2strv( (const wchar_t **) p->argv),
+ env_export_arr( 0 ) );
debug( 0,
_( L"Failed to execute process '%ls'" ),
p->actual_cmd );
@@ -609,21 +611,21 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
if( j->job_control )
{
- int new_pgid=0;
-
if (!j->pgid)
{
- new_pgid=1;
j->pgid = p->pid;
}
if( setpgid (p->pid, j->pgid) )
- {
+ {
if( getpgid( p->pid) != j->pgid && print_errors )
{
debug( 1,
- _( L"Could not send process %d from group %d to group %d" ),
- p->pid,
+ _( L"Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d" ),
+ p->pid,
+ p->argv[0],
+ j->job_id,
+ j->command,
getpgid( p->pid),
j->pgid );
wperror( L"setpgid" );
@@ -671,6 +673,10 @@ void exec( job_t *j )
*/
int exec_error=0;
+ int needs_keepalive = 0;
+ process_t keepalive;
+
+
CHECK( j, );
if( no_exec )
@@ -753,6 +759,53 @@ void exec( job_t *j )
j->io = io_add( j->io, &pipe_write );
signal_block();
+
+ /*
+ See if we need to create a group keepalive process. This is a
+ process that we create to make sure that the process group
+ doesn't die accidentally, and is needed when a block/function is
+ inside a pipeline.
+ */
+
+ if( j->job_control )
+ {
+ for( p=j->first_process; p; p = p->next )
+ {
+ if( (p->type == INTERNAL_BLOCK ) ||
+ (p->type == INTERNAL_FUNCTION ) )
+ {
+ if( p->next )
+ {
+ needs_keepalive = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if( needs_keepalive )
+ {
+ keepalive.pid = fork();
+
+ if( keepalive.pid == 0 )
+ {
+ keepalive.pid = getpid();
+ set_child_group( j, &keepalive, 1 );
+ pause();
+ exit(0);
+ }
+ else if( keepalive.pid < 0 )
+ {
+ /* The fork failed. */
+ debug( 0, FORK_ERROR );
+ wperror (L"fork");
+ exit (1);
+ }
+ else
+ {
+ set_child_group( j, &keepalive, 0 );
+ }
+ }
/*
This loop loops over every process_t in the job, starting it as
@@ -761,7 +814,7 @@ void exec( job_t *j )
The loop also has to handle pipelining between the jobs.
*/
-
+
for( p=j->first_process; p; p = p->next )
{
mypipe[1]=-1;
@@ -1190,7 +1243,7 @@ void exec( job_t *j )
p->pid = getpid();
setup_child_process( j, p );
launch_process( p );
-
+
/*
launch_process _never_ returns...
*/
@@ -1246,6 +1299,15 @@ void exec( job_t *j )
}
}
+ /*
+ The keepalive process is no longer needed, so we terminate it
+ with extreme prejudice
+ */
+ if( needs_keepalive )
+ {
+ kill( keepalive.pid, SIGKILL );
+ }
+
signal_unblock();
debug( 3, L"Job is constructed" );