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
This commit is contained in:
axel 2006-08-27 10:52:52 +10:00
parent 3c8d2a1126
commit 1c86395ed8

80
exec.c
View File

@ -441,7 +441,9 @@ static void launch_process( process_t *p )
{ {
// debug( 1, L"exec '%ls'", p->argv[0] ); // 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, debug( 0,
_( L"Failed to execute process '%ls'" ), _( L"Failed to execute process '%ls'" ),
p->actual_cmd ); 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 ) if( j->job_control )
{ {
int new_pgid=0;
if (!j->pgid) if (!j->pgid)
{ {
new_pgid=1;
j->pgid = p->pid; j->pgid = p->pid;
} }
if( setpgid (p->pid, j->pgid) ) if( setpgid (p->pid, j->pgid) )
{ {
if( getpgid( p->pid) != j->pgid && print_errors ) if( getpgid( p->pid) != j->pgid && print_errors )
{ {
debug( 1, debug( 1,
_( L"Could not send process %d from group %d to group %d" ), _( L"Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d" ),
p->pid, p->pid,
p->argv[0],
j->job_id,
j->command,
getpgid( p->pid), getpgid( p->pid),
j->pgid ); j->pgid );
wperror( L"setpgid" ); wperror( L"setpgid" );
@ -671,6 +673,10 @@ void exec( job_t *j )
*/ */
int exec_error=0; int exec_error=0;
int needs_keepalive = 0;
process_t keepalive;
CHECK( j, ); CHECK( j, );
if( no_exec ) if( no_exec )
@ -753,6 +759,53 @@ void exec( job_t *j )
j->io = io_add( j->io, &pipe_write ); j->io = io_add( j->io, &pipe_write );
signal_block(); 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 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. The loop also has to handle pipelining between the jobs.
*/ */
for( p=j->first_process; p; p = p->next ) for( p=j->first_process; p; p = p->next )
{ {
mypipe[1]=-1; mypipe[1]=-1;
@ -1190,7 +1243,7 @@ void exec( job_t *j )
p->pid = getpid(); p->pid = getpid();
setup_child_process( j, p ); setup_child_process( j, p );
launch_process( p ); launch_process( p );
/* /*
launch_process _never_ returns... 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(); signal_unblock();
debug( 3, L"Job is constructed" ); debug( 3, L"Job is constructed" );