From f83575f08447e91d9c26f3e9ff302b428b2c14a9 Mon Sep 17 00:00:00 2001 From: axel Date: Mon, 30 Oct 2006 07:09:11 +1000 Subject: [PATCH] Make sure signals aren't blocked while autoloading, also add a few consistency checks to see that signals aren't blocked in critical places darcs-hash:20061029210911-ac50b-50bec85c3d59d0332ba44f3ece1a012cdc3e8c4b.gz --- common.h | 38 ++++++++++++++++++++++++++++++++------ exec.c | 17 +++++++++++++---- function.c | 8 -------- parse_util.c | 17 +++++++++++------ parser.c | 5 ++++- proc.c | 5 ++--- signal.c | 9 ++++++++- signal.h | 9 +++++++++ 8 files changed, 79 insertions(+), 29 deletions(-) diff --git a/common.h b/common.h index b787fbe97..99c5671e0 100644 --- a/common.h +++ b/common.h @@ -74,7 +74,7 @@ extern wchar_t *program_name; failiure, the current function is ended at once. The second parameter is the exit status of the current function on failiure. */ -#define CHECK( arg, retval ) \ +#define CHECK( arg, retval ) \ if( !(arg) ) \ { \ debug( 1, \ @@ -85,18 +85,44 @@ extern wchar_t *program_name; #arg, \ PACKAGE_BUGREPORT ); \ return retval; \ - } \ - + } /** Exit program at once, leaving an error message about running out of memory */ -#define DIE_MEM() \ +#define DIE_MEM() \ { \ - fwprintf( stderr, L"fish: Out of memory on line %d of file %s, shutting down fish\n", __LINE__, __FILE__ ); \ + fwprintf( stderr, \ + L"fish: Out of memory on line %d of file %s, shutting down fish\n", \ + __LINE__, \ + __FILE__ ); \ exit(1); \ - } \ + } +/** + Cause fish to crash. This should only be usd for debugging. +*/ +#define CRASH() \ + { \ + int *n = 0; \ + *n = 1; \ + } + +/** + Check if signals are blocked +*/ +#define CHECK_BLOCK( retval ) \ + if( signal_is_blocked() ) \ + { \ + debug( 0, \ + L"function %s called while blocking signals. " \ + L"This is a bug. " \ + L"If you can reproduce it, please send a bug report to %s.", \ + __func__, \ + PACKAGE_BUGREPORT ); \ + return retval; \ + } + /** Shorthand for wgettext call */ diff --git a/exec.c b/exec.c index 3b89a3bcb..dd8ee76bc 100644 --- a/exec.c +++ b/exec.c @@ -682,12 +682,11 @@ void exec( job_t *j ) CHECK( j, ); - + CHECK_BLOCK(); + if( no_exec ) return; - - sigemptyset( &chldset ); sigaddset( &chldset, SIGCHLD ); @@ -873,7 +872,17 @@ void exec( job_t *j ) { case INTERNAL_FUNCTION: { - wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] ))); + const wchar_t * orig_def; + wchar_t * def=0; + + signal_unblock(); + orig_def = function_get_definition( p->argv[0] ); + signal_block(); + + if( orig_def ) + { + def = halloc_register( j, wcsdup(orig_def) ); + } if( def == 0 ) { debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] ); diff --git a/function.c b/function.c index 2e1385618..54a171eda 100644 --- a/function.c +++ b/function.c @@ -353,10 +353,6 @@ const wchar_t *function_get_definition_file( const wchar_t *argv ) CHECK( argv, 0 ); - if( is_autoload ) - return 0; - - load( argv ); data = (function_data_t *)hash_get( &function, argv ); if( data == 0 ) return 0; @@ -371,10 +367,6 @@ int function_get_definition_offset( const wchar_t *argv ) CHECK( argv, -1 ); - if( is_autoload ) - return -1; - - load( argv ); data = (function_data_t *)hash_get( &function, argv ); if( data == 0 ) return -1; diff --git a/parse_util.c b/parse_util.c index af4b20c58..3e939bd9f 100644 --- a/parse_util.c +++ b/parse_util.c @@ -685,6 +685,8 @@ int parse_util_load( const wchar_t *cmd, CHECK( path_var_name, 0 ); CHECK( cmd, 0 ); + CHECK_BLOCK( 0 ); + // debug( 0, L"Autoload %ls in %ls", cmd, path_var_name ); parse_util_autounload( path_var_name, cmd, on_load ); @@ -724,7 +726,6 @@ int parse_util_load( const wchar_t *cmd, */ if( wcscmp( path_var, loaded->old_path ) != 0 ) { - debug( 0, L"path change, new path is %ls", path_var ); parse_util_load_reset( path_var_name, on_load); reload = parse_util_load( cmd, path_var_name, on_load, reload ); return reload; @@ -779,11 +780,15 @@ int parse_util_load( const wchar_t *cmd, res = parse_util_load_internal( cmd, on_load, reload, loaded, path_list ); - /** - Cleanup - */ - hash_remove( &loaded->is_loading, cmd, 0, 0 ); - + autoload_t *loaded2 = (autoload_t *)hash_get( all_loaded, path_var_name ); + if( loaded2 == loaded ) + { + /** + Cleanup + */ + hash_remove( &loaded->is_loading, cmd, 0, 0 ); + } + c2 = al_get_count( path_list ); al_foreach( path_list, &free ); diff --git a/parser.c b/parser.c index e5c0c1fdc..c92367541 100644 --- a/parser.c +++ b/parser.c @@ -42,6 +42,7 @@ The fish parser. Contains functions for parsing code. #include "halloc.h" #include "halloc_util.h" #include "path.h" +#include "signal.h" /** Maximum number of block levels in code. This is not the same as @@ -1699,7 +1700,7 @@ static int parse_job( process_t *p, block_t *prev_block = current_block; int prev_tokenizer_pos = current_tokenizer_pos; - + current_tokenizer_pos = tok_get_pos( tok ); while( al_get_count( args ) == 0 ) @@ -2482,6 +2483,8 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type ) forbidden_function = al_new(); } + CHECK_BLOCK( 1 ); + forbid_count = al_get_count( forbidden_function ); block_io = io; diff --git a/proc.c b/proc.c index e13f8a7c6..72a5d12c1 100644 --- a/proc.c +++ b/proc.c @@ -858,7 +858,7 @@ void job_continue (job_t *j, int cont) first_job = j; job_set_flag( j, JOB_NOTIFIED, 0 ); - debug( 4, + debug( 3, L"Continue job %d (%ls), %ls, %ls", j->job_id, j->command, @@ -895,7 +895,7 @@ void job_continue (job_t *j, int cont) } signal_unblock(); } - + /* Send the job a continue signal, if necessary. */ @@ -931,7 +931,6 @@ void job_continue (job_t *j, int cont) { int quit = 0; -// debug( 1, L"wait loop" ); /* Wait for job to report. Looks a bit ugly because it has to handle the possibility that a signal is dispatched while diff --git a/signal.c b/signal.c index 18fc3eec2..45630208e 100644 --- a/signal.c +++ b/signal.c @@ -650,6 +650,7 @@ void signal_block() } block_count++; +// debug( 0, L"signal block level increased to %d", block_count ); } void signal_unblock() @@ -663,5 +664,11 @@ void signal_unblock() sigfillset( &chldset ); sigprocmask(SIG_UNBLOCK, &chldset, 0); } - +// debug( 0, L"signal block level decreased to %d", block_count ); } + +int signal_is_blocked() +{ + return !!block_count; +} + diff --git a/signal.h b/signal.h index 5fb4a897b..91bddc920 100644 --- a/signal.h +++ b/signal.h @@ -3,6 +3,8 @@ The library for various signal related issues */ +#ifndef FISH_SIGNALH +#define FISH_SIGNALH /** Get the integer signal value representing the specified signal, or @@ -47,3 +49,10 @@ void signal_block(); Unblock all signals */ void signal_unblock(); + +/** + Returns true if signals are being blocked +*/ +int signal_is_blocked(); + +#endif