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,
array_list_t *comp_out )
{
int was_interactive = is_interactive;
array_list_t possible_comp;
int i;
al_init( &possible_comp );
is_interactive=0;
proc_push_interactive(0);
eval_args( args, &possible_comp );
is_interactive=was_interactive;
proc_pop_interactive();
/* We need to unescape these strings before matching them */
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;
array_list_t *fire=0;
int was_interactive = is_interactive;
/*
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
they are marked as non-interactive and as a subshell
*/
is_interactive=0;
proc_push_interactive(0);
parser_push_block( EVENT );
current_block->param1.event = event;
eval( (wchar_t *)b->buff, 0, TOP );
parser_pop_block();
proc_pop_interactive();
}
/*
Restore interactivity flags
*/
is_interactive = was_interactive;
if( 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;
int previous_pos=current_tokenizer_pos;
int do_loop=1;
int was_interactive = is_interactive;
is_interactive = 0;
proc_push_interactive(0);
current_tokenizer_pos = 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_pos = previous_pos;
is_interactive = was_interactive;
proc_pop_interactive();
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 "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "output.h"
/**
Size of message buffer
@ -76,7 +78,7 @@ static int last_status=0;
static sig_atomic_t got_signal=0;
job_t *first_job=0;
int is_interactive=0;
int is_interactive=-1;
int is_interactive_session=0;
int is_subshell=0;
int is_block=0;
@ -101,9 +103,12 @@ static string_buffer_t event_pid;
*/
static string_buffer_t event_status;
static array_list_t *interactive_stack;
void proc_init()
{
interactive_stack = al_halloc( global_context );
proc_push_interactive( 0 );
al_init( &event.arguments );
sb_init( &event_pid );
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();
/**
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

View file

@ -606,7 +606,6 @@ void reader_write_title()
wchar_t *title;
array_list_t l;
wchar_t *term = env_get( L"TERM" );
int was_interactive = is_interactive;
/*
This is a pretty lame heuristic for detecting terminals that do
@ -628,7 +627,7 @@ void reader_write_title()
al_init( &l );
is_interactive = 0;
proc_push_interactive(0);
if( exec_subshell( title, &l ) != -1 )
{
int i;
@ -639,7 +638,7 @@ void reader_write_title()
}
writestr( L"\7" );
}
is_interactive = was_interactive;
proc_pop_interactive();
al_foreach( &l, (void (*)(const void *))&free );
al_destroy( &l );
@ -790,8 +789,8 @@ static void write_prompt()
if( data->prompt )
{
int was_interactive = is_interactive;
is_interactive = 0;
proc_push_interactive( 0 );
if( exec_subshell( data->prompt, &prompt_list ) == -1 )
{
/* 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_init( &prompt_list );
}
is_interactive = was_interactive;
proc_pop_interactive();
}
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
original state. We also update the signal handlers.
*/
int shell_was_interactive = is_interactive;
is_interactive = ((fd == 0) && isatty(STDIN_FILENO));
signal_set_handlers();
proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO)));
res= is_interactive?read_i():read_ni( fd );
@ -2982,7 +2979,6 @@ int reader_read( int fd )
data->end_loop = 0;
end_loop = 0;
is_interactive = shell_was_interactive;
signal_set_handlers();
proc_pop_interactive();
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 )
{
reader_handle_int( sig );
default_handler( sig, info, context);
}
@ -422,6 +421,10 @@ void signal_reset_handlers()
void signal_set_handlers()
{
struct sigaction act;
if( is_interactive == -1 )
return;
sigemptyset( & act.sa_mask );
act.sa_flags=SA_SIGINFO;
act.sa_sigaction = &default_handler;