Rearrange wopen and stat to avoid a race and hopefully improve performance a little bit.

This commit is contained in:
ridiculousfish 2012-03-02 11:12:08 -08:00
parent 17a75a5aa5
commit 2da8df6202
2 changed files with 95 additions and 95 deletions

View file

@ -2746,27 +2746,28 @@ static int builtin_source( parser_t &parser, wchar_t ** argv )
else else
{ {
if( wstat(argv[1], &buf) == -1 ) if( ( fd = wopen_cloexec( argv[1], O_RDONLY ) ) == -1 )
{ {
append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] ); append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
builtin_wperror( L"." ); builtin_wperror( L"." );
return STATUS_BUILTIN_ERROR;
}
if( fstat(fd, &buf) == -1 )
{
close(fd);
append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
builtin_wperror( L"." );
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
if( !S_ISREG(buf.st_mode) ) if( !S_ISREG(buf.st_mode) )
{ {
close(fd);
append_format(stderr_buffer, _( L"%ls: '%ls' is not a file\n" ), argv[0], argv[1] ); append_format(stderr_buffer, _( L"%ls: '%ls' is not a file\n" ), argv[0], argv[1] );
return STATUS_BUILTIN_ERROR; return STATUS_BUILTIN_ERROR;
} }
if( ( fd = wopen_cloexec( argv[1], O_RDONLY ) ) == -1 )
{
append_format(stderr_buffer, _(L"%ls: Error encountered while sourcing file '%ls':\n"), argv[0], argv[1] );
builtin_wperror( L"." );
return STATUS_BUILTIN_ERROR;
}
fn = wrealpath( argv[1], 0 ); fn = wrealpath( argv[1], 0 );
if( !fn ) if( !fn )

View file

@ -1967,91 +1967,91 @@ int parser_t::parse_job( process_t *p,
*/ */
if( p->actual_cmd == NULL ) if( p->actual_cmd == NULL )
{ {
int tmp; int tmp;
const wchar_t *cmd = args.at( 0 ).completion.c_str(); const wchar_t *cmd = args.at( 0 ).completion.c_str();
/* /*
We couldn't find the specified command. We couldn't find the specified command.
What we want to happen now is that the What we want to happen now is that the
specified job won't get executed, and an specified job won't get executed, and an
error message is printed on-screen, but error message is printed on-screen, but
otherwise, the parsing/execution of the otherwise, the parsing/execution of the
file continues. Because of this, we don't file continues. Because of this, we don't
want to call error(), since that would stop want to call error(), since that would stop
execution of the file. Instead we let execution of the file. Instead we let
p->actual_command be 0 (null), which will p->actual_command be 0 (null), which will
cause the job to silently not execute. We cause the job to silently not execute. We
also print an error message and set the also print an error message and set the
status to 127 (This is the standard number status to 127 (This is the standard number
for this, used by other shells like bash for this, used by other shells like bash
and zsh). and zsh).
*/ */
if( wcschr( cmd, L'=' ) ) if( wcschr( cmd, L'=' ) )
{ {
wchar_t *cpy = wcsdup( cmd ); wchar_t *cpy = wcsdup( cmd );
wchar_t *valpart = wcschr( cpy, L'=' ); wchar_t *valpart = wcschr( cpy, L'=' );
*valpart++=0; *valpart++=0;
debug( 0, debug( 0,
COMMAND_ASSIGN_ERR_MSG, COMMAND_ASSIGN_ERR_MSG,
cmd, cmd,
cpy, cpy,
valpart); valpart);
free(cpy); free(cpy);
} }
else if(cmd[0]==L'$') else if(cmd[0]==L'$')
{ {
const env_var_t val_wstr = env_get_string( cmd+1 ); const env_var_t val_wstr = env_get_string( cmd+1 );
const wchar_t *val = val_wstr.missing() ? NULL : val_wstr.c_str(); const wchar_t *val = val_wstr.missing() ? NULL : val_wstr.c_str();
if( val ) if( val )
{ {
debug( 0, debug( 0,
_(L"Variables may not be used as commands. Instead, define a function like 'function %ls; %ls $argv; end'. See the help section for the function command by typing 'help function'." ), _(L"Variables may not be used as commands. Instead, define a function like 'function %ls; %ls $argv; end'. See the help section for the function command by typing 'help function'." ),
cmd+1, cmd+1,
val, val,
cmd ); cmd );
} }
else else
{ {
debug( 0, debug( 0,
_(L"Variables may not be used as commands. Instead, define a function. See the help section for the function command by typing 'help function'." ), _(L"Variables may not be used as commands. Instead, define a function. See the help section for the function command by typing 'help function'." ),
cmd ); cmd );
} }
} }
else if(wcschr( cmd, L'$' )) else if(wcschr( cmd, L'$' ))
{ {
debug( 0, debug( 0,
_(L"Commands may not contain variables. Use the eval builtin instead, like 'eval %ls'. See the help section for the eval command by typing 'help eval'." ), _(L"Commands may not contain variables. Use the eval builtin instead, like 'eval %ls'. See the help section for the eval command by typing 'help eval'." ),
cmd, cmd,
cmd ); cmd );
} }
else if( err!=ENOENT ) else if( err!=ENOENT )
{ {
debug( 0, debug( 0,
_(L"The file '%ls' is not executable by this user"), _(L"The file '%ls' is not executable by this user"),
cmd?cmd:L"UNKNOWN" ); cmd?cmd:L"UNKNOWN" );
} }
else else
{ {
debug( 0, debug( 0,
_(L"Unknown command '%ls'"), _(L"Unknown command '%ls'"),
cmd?cmd:L"UNKNOWN" ); cmd?cmd:L"UNKNOWN" );
} }
tmp = current_tokenizer_pos; tmp = current_tokenizer_pos;
current_tokenizer_pos = tok_get_pos(tok); current_tokenizer_pos = tok_get_pos(tok);
fwprintf( stderr, L"%ls", parser_t::current_line() ); fwprintf( stderr, L"%ls", parser_t::current_line() );
current_tokenizer_pos=tmp; current_tokenizer_pos=tmp;
job_set_flag( j, JOB_SKIP, 1 ); job_set_flag( j, JOB_SKIP, 1 );
event_fire_generic(L"fish_command_not_found", (wchar_t *)( args.at( 0 ).completion.c_str() ) ); event_fire_generic(L"fish_command_not_found", (wchar_t *)( args.at( 0 ).completion.c_str() ) );
proc_set_last_status( err==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE ); proc_set_last_status( err==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE );
} }
} }
} }
@ -2307,8 +2307,7 @@ void parser_t::eval_job( tokenizer *tok )
if( job_start_pos < tok_get_pos( tok ) ) if( job_start_pos < tok_get_pos( tok ) )
{ {
int stop_pos = tok_get_pos( tok ); int stop_pos = tok_get_pos( tok );
const wchar_t *newline = wcschr( tok_string(tok)+start_pos, const wchar_t *newline = wcschr(tok_string(tok)+start_pos, L'\n');
L'\n' );
if( newline ) if( newline )
stop_pos = mini( stop_pos, newline - tok_string(tok) ); stop_pos = mini( stop_pos, newline - tok_string(tok) );