Check return value of a few write calls and retry on EINTR, and fix a few other warnings, mostly by printing error messages before giving up.

darcs-hash:20090222202852-ac50b-b0e79142af5b7a99e55271d4001fa252d9684a1d.gz
This commit is contained in:
axel 2009-02-23 06:28:52 +10:00
parent f71c6f3f0e
commit 14c84ffbcb
13 changed files with 122 additions and 30 deletions

View file

@ -2849,7 +2849,7 @@ static int builtin_source( wchar_t ** argv )
sb_printf( sb_err, sb_printf( sb_err,
_( L"%ls: Error while reading file '%ls'\n" ), _( L"%ls: Error while reading file '%ls'\n" ),
argv[0], argv[0],
fn_intern == L"-" ? L"<stdin>" : fn_intern ); fn_intern == intern_static(L"-") ? L"<stdin>" : fn_intern );
} }
else else
{ {

View file

@ -578,6 +578,36 @@ int read_blocked(int fd, void *buf, size_t count)
return res; return res;
} }
ssize_t write_loop(int fd, char *buff, size_t count)
{
ssize_t out=0;
ssize_t out_cum=0;
while( 1 )
{
out = write( fd,
&buff[out_cum],
count - out_cum );
if (out == -1)
{
if( errno != EAGAIN &&
errno != EINTR )
{
return -1;
}
} else
{
out_cum += out;
}
if( out_cum >= count )
{
break;
}
}
return out_cum;
}
void debug( int level, const wchar_t *msg, ... ) void debug( int level, const wchar_t *msg, ... )
{ {
va_list va; va_list va;
@ -1815,7 +1845,14 @@ double timef()
if( time_res ) if( time_res )
{ {
return nan(0); /*
Fixme: What on earth is the correct parameter value for NaN?
The man pages and the standard helpfully state that this
parameter is implementation defined. Gcc gives a warning if
a null pointer is used. But not even all mighty Google gives
a hint to what value should actually be returned.
*/
return nan("");
} }
return (double)tv.tv_sec + 0.000001*tv.tv_usec; return (double)tv.tv_sec + 0.000001*tv.tv_usec;

View file

@ -331,6 +331,12 @@ __sentinel int contains_internal( const wchar_t *needle, ... );
*/ */
int read_blocked(int fd, void *buf, size_t count); int read_blocked(int fd, void *buf, size_t count);
/**
Loop a write request while failiure is non-critical. Return -1 and set errno
in case of critical error.
*/
ssize_t write_loop(int fd, char *buff, size_t count);
/** /**
Issue a debug message with printf-style string formating and Issue a debug message with printf-style string formating and

35
exec.c
View file

@ -53,6 +53,11 @@
*/ */
#define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" ) #define FD_ERROR _( L"An error occurred while redirecting file descriptor %d" )
/**
file descriptor redirection error message
*/
#define WRITE_ERROR _( L"An error occurred while writing output" )
/** /**
file redirection error message file redirection error message
*/ */
@ -92,6 +97,18 @@ static array_list_t *open_fds=0;
static int set_child_group( job_t *j, process_t *p, int print_errors ); static int set_child_group( job_t *j, process_t *p, int print_errors );
static void exec_write_and_exit( int fd, char *buff, size_t count, int status )
{
if( write_loop(fd, buff, count) == -1 )
{
debug( 0, WRITE_ERROR);
wperror( L"write" );
exit(status);
}
exit( status );
}
void exec_close( int fd ) void exec_close( int fd )
{ {
int i; int i;
@ -1426,15 +1443,17 @@ void exec( job_t *j )
if( pid == 0 ) if( pid == 0 )
{ {
/* /*
This is the child process. Write out the contents of the pipeline. This is the child process. Write out the contents of the pipeline.
*/ */
p->pid = getpid(); p->pid = getpid();
setup_child_process( j, p ); setup_child_process( j, p );
write( io_buffer->fd,
io_buffer->param2.out_buffer->buff, exec_write_and_exit(io_buffer->fd,
io_buffer->param2.out_buffer->used ); io_buffer->param2.out_buffer->buff,
exit( status ); io_buffer->param2.out_buffer->used,
status);
} }
else else
{ {
@ -1480,10 +1499,10 @@ void exec( job_t *j )
p->pid = getpid(); p->pid = getpid();
setup_child_process( j, p ); setup_child_process( j, p );
write( 1, exec_write_and_exit( 1,
input_redirect->param2.out_buffer->buff, input_redirect->param2.out_buffer->buff,
input_redirect->param2.out_buffer->used ); input_redirect->param2.out_buffer->used,
exit( 0 ); 0);
} }
else else
{ {

View file

@ -351,7 +351,7 @@ static int pager_buffered_writer( char c)
*/ */
static void pager_flush() static void pager_flush()
{ {
write( 1, pager_buffer->buff, pager_buffer->used ); write_loop( 1, pager_buffer->buff, pager_buffer->used );
pager_buffer->used = 0; pager_buffer->used = 0;
} }

View file

@ -521,7 +521,7 @@ static void load_or_save( int save)
if( save ) if( save )
{ {
write( c.fd, SAVE_MSG, strlen(SAVE_MSG) ); write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
enqueue_all( &c ); enqueue_all( &c );
} }
else else

View file

@ -94,6 +94,17 @@ license. Read the source code of the library for more information.
*/ */
#define GETOPT_STRING "tfimdalhv" #define GETOPT_STRING "tfimdalhv"
/**
Error message if system call goes wrong.
*/
#define ERROR_SYSTEM "%s: Could not execute command \"%s\"\n"
/**
Exit code if system call goes wrong.
*/
#define STATUS_ERROR_SYSTEM 1
/** /**
All types of input and output possible All types of input and output possible
*/ */
@ -1127,8 +1138,12 @@ static void launch( char *filter, array_list_t *files, int fileno )
writer( '&' ); writer( '&' );
writer( '\0' ); writer( '\0' );
// fprintf( stderr, "mimedb: %s\n", launch_buff ); if( system( launch_buff ) == -1 )
system( launch_buff ); {
fprintf( stderr, _( ERROR_SYSTEM ), MIMEDB, launch_buff );
exit(STATUS_ERROR_SYSTEM);
}
break; break;
} }
} }

View file

@ -362,7 +362,7 @@ void set_color( int c, int c2 )
*/ */
static int writeb_internal( char c ) static int writeb_internal( char c )
{ {
write( 1, &c, 1 ); write_loop( 1, &c, 1 );
return 0; return 0;
} }

View file

@ -436,6 +436,7 @@ typedef struct
/** /**
Return the current number of block nestings Return the current number of block nestings
*/ */
/*
static int block_count( block_t *b ) static int block_count( block_t *b )
{ {
@ -443,7 +444,7 @@ static int block_count( block_t *b )
return 0; return 0;
return( block_count(b->outer)+1); return( block_count(b->outer)+1);
} }
*/
void parser_push_block( int type ) void parser_push_block( int type )
{ {

View file

@ -5,18 +5,26 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "print_help.h" #include "print_help.h"
#define CMD_LEN 1024 #define CMD_LEN 1024
#define HELP_ERR "Could not show help message\n"
void print_help( char *c, int fd ) void print_help( char *c, int fd )
{ {
char cmd[ CMD_LEN]; char cmd[ CMD_LEN];
int printed = snprintf( cmd, CMD_LEN, "fish -c '__fish_print_help %s >&%d'", c, fd ); int printed = snprintf( cmd, CMD_LEN, "fish -c '__fish_print_help %s >&%d'", c, fd );
if( printed < CMD_LEN ) if( printed < CMD_LEN )
system( cmd ); {
if( (system( cmd ) == -1) )
{
write_loop(2, HELP_ERR, strlen(HELP_ERR));
}
}
} }

10
proc.c
View file

@ -356,6 +356,8 @@ static void mark_process_status( job_t *j,
} }
else else
{ {
ssize_t ignore;
/* This should never be reached */ /* This should never be reached */
p->completed = 1; p->completed = 1;
@ -364,8 +366,12 @@ static void mark_process_status( job_t *j,
MESS_SIZE, MESS_SIZE,
"Process %d exited abnormally\n", "Process %d exited abnormally\n",
(int) p->pid ); (int) p->pid );
/*
write( 2, mess, strlen(mess) ); If write fails, do nothing. We're in a signal handlers error
handler. If things aren't working properly, it's safer to
give up.
*/
ignore = write( 2, mess, strlen(mess) );
} }
} }

View file

@ -1577,9 +1577,9 @@ static int handle_completions( array_list_t *comp )
wchar_t quote; wchar_t quote;
get_param( data->buff, data->buff_pos, &quote, 0, 0, 0 ); get_param( data->buff, data->buff_pos, &quote, 0, 0, 0 );
is_quoted = (quote != L'\0'); is_quoted = (quote != L'\0');
write(1, "\n", 1 ); write_loop(1, "\n", 1 );
run_pager( prefix, is_quoted, comp ); run_pager( prefix, is_quoted, comp );
} }
@ -2650,7 +2650,7 @@ wchar_t *reader_readline()
case R_REPAINT: case R_REPAINT:
{ {
exec_prompt(); exec_prompt();
write( 1, "\r", 1 ); write_loop( 1, "\r", 1 );
s_reset( &data->screen, 0 ); s_reset( &data->screen, 0 );
reader_repaint(); reader_repaint();
break; break;

View file

@ -337,7 +337,7 @@ static void s_check_status( screen_t *s)
*/ */
int prev_line = s->actual_cursor[1]; int prev_line = s->actual_cursor[1];
write( 1, "\r", 1 ); write_loop( 1, "\r", 1 );
s_reset( s, 0 ); s_reset( s, 0 );
s->actual_cursor[1] = prev_line; s->actual_cursor[1] = prev_line;
} }
@ -756,7 +756,7 @@ static void s_update( screen_t *scr, wchar_t *prompt )
if( output.used ) if( output.used )
{ {
write( 1, output.buff, output.used ); write_loop( 1, output.buff, output.used );
} }
b_destroy( &output ); b_destroy( &output );
@ -804,9 +804,9 @@ void s_write( screen_t *s,
char *prompt_narrow = wcs2str( prompt ); char *prompt_narrow = wcs2str( prompt );
char *buffer_narrow = wcs2str( b ); char *buffer_narrow = wcs2str( b );
write( 1, "\r", 1 ); write_loop( 1, "\r", 1 );
write( 1, prompt_narrow, strlen( prompt_narrow ) ); write_loop( 1, prompt_narrow, strlen( prompt_narrow ) );
write( 1, buffer_narrow, strlen( buffer_narrow ) ); write_loop( 1, buffer_narrow, strlen( buffer_narrow ) );
free( prompt_narrow ); free( prompt_narrow );
free( buffer_narrow ); free( buffer_narrow );
@ -938,7 +938,7 @@ void s_reset( screen_t *s, int reset_cursor )
This should prevent reseting the cursor position during the This should prevent reseting the cursor position during the
next repaint. next repaint.
*/ */
write( 1, "\r", 1 ); write_loop( 1, "\r", 1 );
s->actual_cursor[1] = prev_line; s->actual_cursor[1] = prev_line;
} }
fstat( 1, &s->prev_buff_1 ); fstat( 1, &s->prev_buff_1 );