Fix the longstanding hang-on-exit bug in eterm, as well as making sure the history is saved when the terminal emulator exits

darcs-hash:20060514101623-ac50b-f8ce693ec111e3c158640ef8de309bf7e5484c5b.gz
This commit is contained in:
axel 2006-05-14 20:16:23 +10:00
parent 92ecc01baa
commit 9ebdc16be6
12 changed files with 141 additions and 40 deletions

View File

@ -1857,7 +1857,7 @@ static int builtin_exit( wchar_t **argv )
return 1;
}
reader_exit( 1 );
reader_exit( 1, 0 );
return ec;
}

22
event.c
View File

@ -653,3 +653,25 @@ void event_free( event_t *e )
free( (void *)e->param1.variable );
free( e );
}
int event_signal_listen( int signal )
{
int i;
if( !events )
return 0;
for( i=0; i<al_get_count( events ); i++ )
{
event_t *e = (event_t *)al_get( events, i );
if( e->type == EVENT_SIGNAL &&
(e->param1.signal == signal || e->param1.signal == EVENT_ANY_SIGNAL) )
{
return 1;
}
}
return 0;
}

View File

@ -136,4 +136,9 @@ void event_free( event_t *e );
*/
const wchar_t *event_get_desc( event_t *e );
/**
Returns a non-zero status if there are event listeners that fire on the specified signal
*/
int event_signal_listen( int signal );
#endif

View File

@ -119,7 +119,8 @@ const wchar_t *name_arr[] =
L"history-token-search-backward",
L"history-token-search-forward",
L"self-insert",
L"null"
L"null",
L"eof"
}
;
@ -155,7 +156,8 @@ const wchar_t *desc_arr[] =
L"Search backward through list of previous commands for matching token",
L"Search forward through list of previous commands for matching token",
L"Insert the pressed key",
L"Do nothing"
L"Do nothing",
L"End of file"
}
;
@ -191,7 +193,8 @@ const wchar_t code_arr[] =
R_HISTORY_TOKEN_SEARCH_BACKWARD,
R_HISTORY_TOKEN_SEARCH_FORWARD,
R_SELF_INSERT,
R_NULL
R_NULL,
R_EOF
}
;

View File

@ -17,7 +17,7 @@ inputrc information for key bindings.
*/
enum
{
R_BEGINNING_OF_LINE = R_NULL+1,
R_BEGINNING_OF_LINE = R_NULL+10, /* This give input_common ten slots for lowlevel keycodes */
R_END_OF_LINE,
R_FORWARD_CHAR,
R_BACKWARD_CHAR,

View File

@ -64,7 +64,7 @@ static wint_t readb()
{
unsigned char arr[1];
int do_loop = 0;
do
{
fd_set fd;
@ -93,17 +93,21 @@ static wint_t readb()
{
int res = interrupt_handler();
if( res )
{
return res;
}
}
do_loop = 1;
break;
}
default:
{
debug( 0, L"Error while reading input from keyboard, shutting down" );
wperror(L"read");
exit(1);
/*
The teminal has been closed. Save and exit.
*/
return R_EOF;
}
}
}
@ -120,11 +124,12 @@ static wint_t readb()
}
if( FD_ISSET( 0, &fd ) )
{
if( read_blocked( 0, arr, 1 ) == -1 )
if( read_blocked( 0, arr, 1 ) != 1 )
{
debug( 0, L"Error while reading input from keyboard, shutting down" );
wperror(L"read");
exit(1);
/*
The teminal has been closed. Save and exit.
*/
return R_EOF;
}
do_loop = 0;
}
@ -179,8 +184,8 @@ wchar_t input_common_readch( int timed )
int sz;
if( b == R_NULL )
return R_NULL;
if( (b == R_NULL) || (b == R_EOF) )
return b;
bb=b;

View File

@ -20,7 +20,8 @@ enum
requested but none could be delivered, or when an exception
happened.
*/
R_NULL = INPUT_COMMON_RESERVED
R_NULL = INPUT_COMMON_RESERVED,
R_EOF
}
;

7
main.c
View File

@ -276,7 +276,7 @@ int main( int argc, char **argv )
wchar_t *cmd_wcs = str2wcs( cmd );
res = eval( cmd_wcs, 0, TOP );
free(cmd_wcs);
reader_exit(0);
reader_exit(0, 0);
}
else
{
@ -336,9 +336,9 @@ int main( int argc, char **argv )
}
}
}
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
history_destroy();
complete_destroy();
proc_destroy();
@ -355,5 +355,6 @@ int main( int argc, char **argv )
halloc_util_destroy();
intern_free_all();
return res;
}

View File

@ -232,6 +232,11 @@ typedef struct reader_data
When this is true, the reader will exit
*/
int end_loop;
/**
If this is true, exit reader even if there are running
jobs. This happens if we press e.g. ^D twice.
*/
int prev_end_loop;
/**
Pointer to previous reader_data
@ -299,6 +304,11 @@ static void reader_save_status();
static void reader_check_status();
static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int pos, array_list_t *error );
/**
Variable to keep track of forced exits - see \c reader_exit_forced();
*/
static int exit_forced;
/**
Give up control of terminal
@ -370,6 +380,12 @@ static int room_for_usec(struct stat *st)
return res;
}
int reader_exit_forced()
{
return exit_forced;
}
/**
string_buffer used as temporary storage for the reader_readline function
*/
@ -869,11 +885,14 @@ void reader_destroy()
}
void reader_exit( int do_exit )
void reader_exit( int do_exit, int forced )
{
if( data )
data->end_loop=do_exit;
end_loop=do_exit;
if( forced )
exit_forced = 1;
}
void repaint()
@ -2230,7 +2249,6 @@ int exit_status()
*/
static int read_i()
{
int prev_end_loop=0;
reader_push(L"fish");
reader_set_complete_function( &complete );
@ -2238,6 +2256,7 @@ static int read_i()
reader_set_test_function( &shell_test );
data->prompt_width=60;
data->prev_end_loop=0;
while( (!data->end_loop) && (!sanity_check()) )
{
@ -2254,12 +2273,7 @@ static int read_i()
during evaluation.
*/
tmp = wcsdup( reader_readline() );
data->buff_pos=data->buff_len=0;
data->buff[data->buff_len]=L'\0';
reader_run_command( tmp );
free( tmp );
tmp = reader_readline();
if( data->end_loop)
{
@ -2275,17 +2289,24 @@ static int read_i()
}
}
if( !prev_end_loop && has_job )
if( !reader_exit_forced() && !data->prev_end_loop && has_job )
{
writestr(_( L"There are stopped jobs\n" ));
write_prompt();
data->end_loop = 0;
prev_end_loop=1;
data->prev_end_loop=1;
}
}
else
{
prev_end_loop=0;
tmp = wcsdup( tmp );
data->buff_pos=data->buff_len=0;
data->buff[data->buff_len]=L'\0';
reader_run_command( tmp );
free( tmp );
data->prev_end_loop=0;
}
}
@ -2442,6 +2463,14 @@ wchar_t *reader_readline()
break;
}
case R_EOF:
{
exit_forced = 1;
data->end_loop=1;
debug( 1, L"got R_EOF" );
break;
}
/* complete */
case R_COMPLETE:
{
@ -2833,14 +2862,17 @@ wchar_t *reader_readline()
}
al_destroy( &comp );
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
{
wperror(L"tcsetattr");
exit(1);
}
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
if( !reader_exit_forced() )
{
if( tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
{
wperror(L"tcsetattr");
exit(1);
}
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
}
return data->buff;
}

View File

@ -21,7 +21,7 @@ int reader_read( int fd);
/**
Tell the shell that it should exit after the currently running command finishes.
*/
void reader_exit( int do_exit );
void reader_exit( int do_exit, int force );
/**
Check that the reader is in a sane state
@ -162,5 +162,10 @@ void reader_replace_current_token( wchar_t *new_token );
*/
void reader_handle_int( int signal );
/**
This function returns true if fish is exiting by force, i.e. because stdin died
*/
int reader_exit_forced();
#endif

View File

@ -367,6 +367,7 @@ const wchar_t *signal_get_desc( int sig )
static void default_handler(int signal, siginfo_t *info, void *context)
{
event_t e;
e.type=EVENT_SIGNAL;
e.param1.signal = signal;
e.function_name=0;
@ -383,6 +384,22 @@ static void handle_winch( int sig, siginfo_t *info, void *context )
default_handler( sig, 0, 0 );
}
/**
Respond to a winch signal by checking the terminal size
*/
static void handle_hup( int sig, siginfo_t *info, void *context )
{
if( event_signal_listen( SIGHUP ) )
{
default_handler( sig, 0, 0 );
}
else
{
reader_exit( 1, 1 );
}
}
/**
Interactive mode ^C handler. Respond to int signal by setting
interrupted-flag and stopping all loops and conditionals.
@ -479,7 +496,7 @@ void signal_set_handlers()
wperror( L"sigaction" );
exit(1);
}
act.sa_flags = SA_SIGINFO;
act.sa_sigaction= &handle_winch;
if( sigaction( SIGWINCH, &act, 0 ) )
@ -488,6 +505,14 @@ void signal_set_handlers()
exit(1);
}
act.sa_flags = SA_SIGINFO;
act.sa_sigaction= &handle_hup;
if( sigaction( SIGHUP, &act, 0 ) )
{
wperror( L"sigaction" );
exit(1);
}
}
else
{
@ -510,6 +535,7 @@ void signal_set_handlers()
exit(1);
}
}
}
void signal_handle( int sig, int do_handle )

1
util.c
View File

@ -809,6 +809,7 @@ int wcsfilecmp( const wchar_t *a, const wchar_t *b )
{
return 1;
}
int secondary_diff=0;
if( iswdigit( *a ) && iswdigit( *b ) )
{