Fix bug in fish causing occasionally incorrect signal handlers

darcs-hash:20060216133632-ac50b-f24c049830f9c6deca50aca640189ad3f87b630a.gz
This commit is contained in:
axel 2006-02-16 23:36:32 +10:00
parent 777a559e12
commit cc69afc4fe
7 changed files with 61 additions and 37 deletions

View file

@ -1338,16 +1338,15 @@ static void complete_from_args( const wchar_t *str,
const wchar_t *desc, const wchar_t *desc,
array_list_t *comp_out ) array_list_t *comp_out )
{ {
int was_interactive = is_interactive;
array_list_t possible_comp; array_list_t possible_comp;
int i; int i;
al_init( &possible_comp ); al_init( &possible_comp );
is_interactive=0; proc_push_interactive(0);
eval_args( args, &possible_comp ); eval_args( args, &possible_comp );
is_interactive=was_interactive; proc_pop_interactive();
/* We need to unescape these strings before matching them */ /* We need to unescape these strings before matching them */
for( i=0; i< al_get_count( &possible_comp ); i++ ) for( i=0; i< al_get_count( &possible_comp ); i++ )

11
event.c
View file

@ -386,8 +386,6 @@ static void event_fire_internal( event_t *event )
string_buffer_t *b=0; string_buffer_t *b=0;
array_list_t *fire=0; array_list_t *fire=0;
int was_interactive = is_interactive;
/* /*
First we free all events that have been removed First we free all events that have been removed
*/ */
@ -462,19 +460,14 @@ static void event_fire_internal( event_t *event )
Event handlers are not part of the main flow of code, so Event handlers are not part of the main flow of code, so
they are marked as non-interactive and as a subshell they are marked as non-interactive and as a subshell
*/ */
is_interactive=0; proc_push_interactive(0);
parser_push_block( EVENT ); parser_push_block( EVENT );
current_block->param1.event = event; current_block->param1.event = event;
eval( (wchar_t *)b->buff, 0, TOP ); eval( (wchar_t *)b->buff, 0, TOP );
parser_pop_block(); parser_pop_block();
proc_pop_interactive();
} }
/*
Restore interactivity flags
*/
is_interactive = was_interactive;
if( b ) if( b )
{ {
sb_destroy( b ); sb_destroy( b );

View file

@ -917,9 +917,9 @@ int eval_args( const wchar_t *line, array_list_t *args )
tokenizer *previous_tokenizer=current_tokenizer; tokenizer *previous_tokenizer=current_tokenizer;
int previous_pos=current_tokenizer_pos; int previous_pos=current_tokenizer_pos;
int do_loop=1; int do_loop=1;
int was_interactive = is_interactive;
is_interactive = 0; proc_push_interactive(0);
current_tokenizer_pos = 0; current_tokenizer_pos = 0;
tok_init( &tok, line, 0 ); tok_init( &tok, line, 0 );
@ -978,7 +978,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
current_tokenizer=previous_tokenizer; current_tokenizer=previous_tokenizer;
current_tokenizer_pos = previous_pos; current_tokenizer_pos = previous_pos;
is_interactive = was_interactive; proc_pop_interactive();
return 1; return 1;
} }

23
proc.c
View file

@ -54,6 +54,8 @@ Some of the code in this file is based on code from the Glibc manual.
#include "event.h" #include "event.h"
#include "translate.h" #include "translate.h"
#include "halloc.h" #include "halloc.h"
#include "halloc_util.h"
#include "output.h"
/** /**
Size of message buffer Size of message buffer
@ -76,7 +78,7 @@ static int last_status=0;
static sig_atomic_t got_signal=0; static sig_atomic_t got_signal=0;
job_t *first_job=0; job_t *first_job=0;
int is_interactive=0; int is_interactive=-1;
int is_interactive_session=0; int is_interactive_session=0;
int is_subshell=0; int is_subshell=0;
int is_block=0; int is_block=0;
@ -101,9 +103,12 @@ static string_buffer_t event_pid;
*/ */
static string_buffer_t event_status; static string_buffer_t event_status;
static array_list_t *interactive_stack;
void proc_init() void proc_init()
{ {
interactive_stack = al_halloc( global_context );
proc_push_interactive( 0 );
al_init( &event.arguments ); al_init( &event.arguments );
sb_init( &event_pid ); sb_init( &event_pid );
sb_init( &event_status ); sb_init( &event_status );
@ -1077,3 +1082,19 @@ void proc_sanity_check()
} }
} }
void proc_push_interactive( int value )
{
int old = is_interactive;
al_push( interactive_stack, (void *)(long)is_interactive );
is_interactive = value;
if( old != value )
signal_set_handlers();
}
void proc_pop_interactive()
{
int old = is_interactive;
is_interactive= (int)(long)al_pop(interactive_stack);
if( is_interactive != old )
signal_set_handlers();
}

12
proc.h
View file

@ -337,4 +337,16 @@ void proc_init();
*/ */
void proc_destroy(); void proc_destroy();
/**
Set new value for is_interactive flag, saving previous value. If
needed, update signal handlers.
*/
void proc_push_interactive( int value );
/**
Set is_interactive flag to the previous value. If needed, update
signal handlers.
*/
void proc_pop_interactive();
#endif #endif

View file

@ -606,7 +606,6 @@ void reader_write_title()
wchar_t *title; wchar_t *title;
array_list_t l; array_list_t l;
wchar_t *term = env_get( L"TERM" ); wchar_t *term = env_get( L"TERM" );
int was_interactive = is_interactive;
/* /*
This is a pretty lame heuristic for detecting terminals that do This is a pretty lame heuristic for detecting terminals that do
@ -628,7 +627,7 @@ void reader_write_title()
al_init( &l ); al_init( &l );
is_interactive = 0; proc_push_interactive(0);
if( exec_subshell( title, &l ) != -1 ) if( exec_subshell( title, &l ) != -1 )
{ {
int i; int i;
@ -639,7 +638,7 @@ void reader_write_title()
} }
writestr( L"\7" ); writestr( L"\7" );
} }
is_interactive = was_interactive; proc_pop_interactive();
al_foreach( &l, (void (*)(const void *))&free ); al_foreach( &l, (void (*)(const void *))&free );
al_destroy( &l ); al_destroy( &l );
@ -790,8 +789,8 @@ static void write_prompt()
if( data->prompt ) if( data->prompt )
{ {
int was_interactive = is_interactive; proc_push_interactive( 0 );
is_interactive = 0;
if( exec_subshell( data->prompt, &prompt_list ) == -1 ) if( exec_subshell( data->prompt, &prompt_list ) == -1 )
{ {
/* If executing the prompt fails, make sure we at least don't print any junk */ /* If executing the prompt fails, make sure we at least don't print any junk */
@ -799,7 +798,7 @@ static void write_prompt()
al_destroy( &prompt_list ); al_destroy( &prompt_list );
al_init( &prompt_list ); al_init( &prompt_list );
} }
is_interactive = was_interactive; proc_pop_interactive();
} }
data->prompt_width=calc_prompt_width( &prompt_list ); data->prompt_width=calc_prompt_width( &prompt_list );
@ -2967,10 +2966,8 @@ int reader_read( int fd )
we need to preserve is_interactive, so we save the we need to preserve is_interactive, so we save the
original state. We also update the signal handlers. original state. We also update the signal handlers.
*/ */
int shell_was_interactive = is_interactive;
is_interactive = ((fd == 0) && isatty(STDIN_FILENO)); proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO)));
signal_set_handlers();
res= is_interactive?read_i():read_ni( fd ); res= is_interactive?read_i():read_ni( fd );
@ -2982,7 +2979,6 @@ int reader_read( int fd )
data->end_loop = 0; data->end_loop = 0;
end_loop = 0; end_loop = 0;
is_interactive = shell_was_interactive; proc_pop_interactive();
signal_set_handlers();
return res; return res;
} }

View file

@ -387,7 +387,6 @@ static void handle_winch( int sig, siginfo_t *info, void *context )
static void handle_int( int sig, siginfo_t *info, void *context ) static void handle_int( int sig, siginfo_t *info, void *context )
{ {
reader_handle_int( sig ); reader_handle_int( sig );
default_handler( sig, info, context); default_handler( sig, info, context);
} }
@ -422,6 +421,10 @@ void signal_reset_handlers()
void signal_set_handlers() void signal_set_handlers()
{ {
struct sigaction act; struct sigaction act;
if( is_interactive == -1 )
return;
sigemptyset( & act.sa_mask ); sigemptyset( & act.sa_mask );
act.sa_flags=SA_SIGINFO; act.sa_flags=SA_SIGINFO;
act.sa_sigaction = &default_handler; act.sa_sigaction = &default_handler;