aboutsummaryrefslogtreecommitdiffhomepage
path: root/postfork.cpp
diff options
context:
space:
mode:
authorGravatar Łukasz Niemier <lukasz@niemier.pl>2012-11-18 11:23:22 +0100
committerGravatar Łukasz Niemier <lukasz@niemier.pl>2012-11-18 11:23:22 +0100
commit47df1ae40adecd0a02fc7dd06ab0745cb18c3fe0 (patch)
tree13bf3e8fdcae60fdfb5fa5e26c95818dc7a49790 /postfork.cpp
parentb79854ad1aa814d9d35d76a1929b4726fa4bffa5 (diff)
Remove trailing whitespaces and change tabs to spaces
Diffstat (limited to 'postfork.cpp')
-rw-r--r--postfork.cpp640
1 files changed, 320 insertions, 320 deletions
diff --git a/postfork.cpp b/postfork.cpp
index 4379ca2d..2609831f 100644
--- a/postfork.cpp
+++ b/postfork.cpp
@@ -1,6 +1,6 @@
/** \file postfork.cpp
- Functions that we may safely call after fork().
+ Functions that we may safely call after fork().
*/
#include <fcntl.h>
@@ -44,61 +44,61 @@ static void debug_safe_int(int level, const char *format, int val)
// PCA These calls to debug are rather sketchy because they may allocate memory. Fortunately they only occur if an error occurs.
int set_child_group( job_t *j, process_t *p, int print_errors )
{
- int res = 0;
-
- if( job_get_flag( j, JOB_CONTROL ) )
- {
- if (!j->pgid)
- {
- j->pgid = p->pid;
- }
-
- if( setpgid (p->pid, j->pgid) )
- {
- if( getpgid( p->pid) != j->pgid && print_errors )
- {
+ int res = 0;
+
+ if( job_get_flag( j, JOB_CONTROL ) )
+ {
+ if (!j->pgid)
+ {
+ j->pgid = p->pid;
+ }
+
+ if( setpgid (p->pid, j->pgid) )
+ {
+ if( getpgid( p->pid) != j->pgid && print_errors )
+ {
char pid_buff[128];
char job_id_buff[128];
char getpgid_buff[128];
char job_pgid_buff[128];
-
+
format_long_safe(pid_buff, p->pid);
format_long_safe(job_id_buff, j->job_id);
format_long_safe(getpgid_buff, getpgid( p->pid));
format_long_safe(job_pgid_buff, j->pgid);
-
- debug_safe( 1,
- "Could not send process %s, '%s' in job %s, '%s' from group %s to group %s",
- pid_buff,
- p->argv0_cstr(),
- job_id_buff,
- j->command_cstr(),
- getpgid_buff,
- job_pgid_buff );
-
- wperror( L"setpgid" );
- res = -1;
- }
- }
- }
- else
- {
- j->pgid = getpid();
- }
-
- if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
- {
- if( tcsetpgrp (0, j->pgid) && print_errors )
- {
+
+ debug_safe( 1,
+ "Could not send process %s, '%s' in job %s, '%s' from group %s to group %s",
+ pid_buff,
+ p->argv0_cstr(),
+ job_id_buff,
+ j->command_cstr(),
+ getpgid_buff,
+ job_pgid_buff );
+
+ wperror( L"setpgid" );
+ res = -1;
+ }
+ }
+ }
+ else
+ {
+ j->pgid = getpid();
+ }
+
+ if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
+ {
+ if( tcsetpgrp (0, j->pgid) && print_errors )
+ {
char job_id_buff[128];
format_long_safe(job_id_buff, j->job_id);
- debug_safe( 1, "Could not send job %s ('%s') to foreground", job_id_buff, j->command_cstr() );
- wperror( L"tcsetpgrp" );
- res = -1;
- }
- }
+ debug_safe( 1, "Could not send job %s ('%s') to foreground", job_id_buff, j->command_cstr() );
+ wperror( L"tcsetpgrp" );
+ res = -1;
+ }
+ }
- return res;
+ return res;
}
/** Make sure the fd used by each redirection is not used by a pipe. */
@@ -108,7 +108,7 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
for (size_t i = 0; i < max; i++)
{
int fd_to_free = io_chain.at(i)->fd;
-
+
/* We only have to worry about fds beyond the three standard ones */
if (fd_to_free <= 2)
continue;
@@ -120,14 +120,14 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
io_data_t *possible_conflict = io_chain.at(j);
if (possible_conflict->io_mode != IO_PIPE && possible_conflict->io_mode != IO_BUFFER)
continue;
-
+
/* If the pipe is a conflict, dup it to some other value */
for (int k=0; k<2; k++)
{
/* If it's not a conflict, we don't care */
if (possible_conflict->param1.pipe_fd[k] != fd_to_free)
continue;
-
+
/* Repeat until we have a replacement fd */
int replacement_fd = -1;
while (replacement_fd < 0)
@@ -143,7 +143,7 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
possible_conflict->param1.pipe_fd[k] = replacement_fd;
}
}
- }
+ }
}
@@ -162,149 +162,149 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain)
static int handle_child_io( io_chain_t &io_chain )
{
- close_unused_internal_pipes( io_chain );
+ close_unused_internal_pipes( io_chain );
free_redirected_fds_from_pipes(io_chain);
- for (size_t idx = 0; idx < io_chain.size(); idx++)
- {
+ for (size_t idx = 0; idx < io_chain.size(); idx++)
+ {
io_data_t *io = io_chain.at(idx);
- int tmp;
-
- if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
- {
- continue;
- }
-
- switch( io->io_mode )
- {
- case IO_CLOSE:
- {
- if( close(io->fd) )
- {
- debug_safe_int( 0, "Failed to close file descriptor %s", io->fd );
- wperror( L"close" );
- }
- break;
- }
-
- case IO_FILE:
- {
- // Here we definitely do not want to set CLO_EXEC because our child needs access
- if( (tmp=open( io->filename_cstr,
- io->param2.flags, OPEN_MASK ) )==-1 )
- {
- if( ( io->param2.flags & O_EXCL ) &&
- ( errno ==EEXIST ) )
- {
- debug_safe( 1, NOCLOB_ERROR, io->filename_cstr );
- }
- else
- {
- debug_safe( 1, FILE_ERROR, io->filename_cstr );
- perror( "open" );
- }
-
- return -1;
- }
- else if( tmp != io->fd)
- {
- /*
- This call will sometimes fail, but that is ok,
- this is just a precausion.
- */
- close(io->fd);
-
- if(dup2( tmp, io->fd ) == -1 )
- {
- debug_safe_int( 1, FD_ERROR, io->fd );
- perror( "dup2" );
- return -1;
- }
- exec_close( tmp );
- }
- break;
- }
-
- case IO_FD:
- {
- /*
- This call will sometimes fail, but that is ok,
- this is just a precausion.
- */
- close(io->fd);
-
- if( dup2( io->param1.old_fd, io->fd ) == -1 )
- {
- debug_safe_int( 1, FD_ERROR, io->fd );
- wperror( L"dup2" );
- return -1;
- }
- break;
- }
-
- case IO_BUFFER:
- case IO_PIPE:
- {
+ int tmp;
+
+ if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
+ {
+ continue;
+ }
+
+ switch( io->io_mode )
+ {
+ case IO_CLOSE:
+ {
+ if( close(io->fd) )
+ {
+ debug_safe_int( 0, "Failed to close file descriptor %s", io->fd );
+ wperror( L"close" );
+ }
+ break;
+ }
+
+ case IO_FILE:
+ {
+ // Here we definitely do not want to set CLO_EXEC because our child needs access
+ if( (tmp=open( io->filename_cstr,
+ io->param2.flags, OPEN_MASK ) )==-1 )
+ {
+ if( ( io->param2.flags & O_EXCL ) &&
+ ( errno ==EEXIST ) )
+ {
+ debug_safe( 1, NOCLOB_ERROR, io->filename_cstr );
+ }
+ else
+ {
+ debug_safe( 1, FILE_ERROR, io->filename_cstr );
+ perror( "open" );
+ }
+
+ return -1;
+ }
+ else if( tmp != io->fd)
+ {
+ /*
+ This call will sometimes fail, but that is ok,
+ this is just a precausion.
+ */
+ close(io->fd);
+
+ if(dup2( tmp, io->fd ) == -1 )
+ {
+ debug_safe_int( 1, FD_ERROR, io->fd );
+ perror( "dup2" );
+ return -1;
+ }
+ exec_close( tmp );
+ }
+ break;
+ }
+
+ case IO_FD:
+ {
+ /*
+ This call will sometimes fail, but that is ok,
+ this is just a precausion.
+ */
+ close(io->fd);
+
+ if( dup2( io->param1.old_fd, io->fd ) == -1 )
+ {
+ debug_safe_int( 1, FD_ERROR, io->fd );
+ wperror( L"dup2" );
+ return -1;
+ }
+ break;
+ }
+
+ case IO_BUFFER:
+ case IO_PIPE:
+ {
/* If write_pipe_idx is 0, it means we're connecting to the read end (first pipe fd). If it's 1, we're connecting to the write end (second pipe fd). */
- unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
+ unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
/*
- debug( 0,
- L"%ls %ls on fd %d (%d %d)",
- write_pipe?L"write":L"read",
- (io->io_mode == IO_BUFFER)?L"buffer":L"pipe",
- io->fd,
- io->param1.pipe_fd[0],
- io->param1.pipe_fd[1]);
+ debug( 0,
+ L"%ls %ls on fd %d (%d %d)",
+ write_pipe?L"write":L"read",
+ (io->io_mode == IO_BUFFER)?L"buffer":L"pipe",
+ io->fd,
+ io->param1.pipe_fd[0],
+ io->param1.pipe_fd[1]);
*/
- if( dup2( io->param1.pipe_fd[write_pipe_idx], io->fd ) != io->fd )
- {
- debug_safe( 1, LOCAL_PIPE_ERROR );
- perror( "dup2" );
- return -1;
- }
-
+ if( dup2( io->param1.pipe_fd[write_pipe_idx], io->fd ) != io->fd )
+ {
+ debug_safe( 1, LOCAL_PIPE_ERROR );
+ perror( "dup2" );
+ return -1;
+ }
+
if (io->param1.pipe_fd[0] >= 0)
exec_close( io->param1.pipe_fd[0]);
if (io->param1.pipe_fd[1] >= 0)
exec_close( io->param1.pipe_fd[1]);
- break;
- }
-
- }
- }
-
- return 0;
-
+ break;
+ }
+
+ }
+ }
+
+ return 0;
+
}
int setup_child_process( job_t *j, process_t *p )
{
- bool ok=true;
-
- if( p )
- {
- ok = (0 == set_child_group( j, p, 1 ));
- }
-
- if( ok )
- {
- ok = (0 == handle_child_io( j->io ));
- if( p != 0 && ! ok )
- {
- exit_without_destructors( 1 );
- }
- }
-
- /* Set the handling for job control signals back to the default. */
- if( ok )
- {
- signal_reset_handlers();
- }
-
- /* Remove all signal blocks */
- signal_unblock();
-
- return ok ? 0 : -1;
+ bool ok=true;
+
+ if( p )
+ {
+ ok = (0 == set_child_group( j, p, 1 ));
+ }
+
+ if( ok )
+ {
+ ok = (0 == handle_child_io( j->io ));
+ if( p != 0 && ! ok )
+ {
+ exit_without_destructors( 1 );
+ }
+ }
+
+ /* Set the handling for job control signals back to the default. */
+ if( ok )
+ {
+ signal_reset_handlers();
+ }
+
+ /* Remove all signal blocks */
+ signal_unblock();
+
+ return ok ? 0 : -1;
}
int g_fork_count = 0;
@@ -318,47 +318,47 @@ int g_fork_count = 0;
pid_t execute_fork(bool wait_for_threads_to_die)
{
ASSERT_IS_MAIN_THREAD();
-
+
if (wait_for_threads_to_die) {
/* Make sure we have no outstanding threads before we fork. This is a pretty sketchy thing to do here, both because exec.cpp shouldn't have to know about iothreads, and because the completion handlers may do unexpected things. */
iothread_drain_all();
}
-
- pid_t pid;
- struct timespec pollint;
- int i;
-
+
+ pid_t pid;
+ struct timespec pollint;
+ int i;
+
g_fork_count++;
-
- for( i=0; i<FORK_LAPS; i++ )
- {
- pid = fork();
- if( pid >= 0)
- {
- return pid;
- }
-
- if( errno != EAGAIN )
- {
- break;
- }
-
- pollint.tv_sec = 0;
- pollint.tv_nsec = FORK_SLEEP_TIME;
-
- /*
- Don't sleep on the final lap - sleeping might change the
- value of errno, which will break the error reporting below.
- */
- if( i != FORK_LAPS-1 )
- {
- nanosleep( &pollint, NULL );
- }
- }
-
- debug_safe( 0, FORK_ERROR );
- wperror (L"fork");
- FATAL_EXIT();
+
+ for( i=0; i<FORK_LAPS; i++ )
+ {
+ pid = fork();
+ if( pid >= 0)
+ {
+ return pid;
+ }
+
+ if( errno != EAGAIN )
+ {
+ break;
+ }
+
+ pollint.tv_sec = 0;
+ pollint.tv_nsec = FORK_SLEEP_TIME;
+
+ /*
+ Don't sleep on the final lap - sleeping might change the
+ value of errno, which will break the error reporting below.
+ */
+ if( i != FORK_LAPS-1 )
+ {
+ nanosleep( &pollint, NULL );
+ }
+ }
+
+ debug_safe( 0, FORK_ERROR );
+ wperror (L"fork");
+ FATAL_EXIT();
return 0;
}
@@ -369,18 +369,18 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
if (posix_spawnattr_init(attr) != 0) {
return false;
}
-
+
if (posix_spawn_file_actions_init(actions) != 0) {
posix_spawnattr_destroy(attr);
return false;
}
-
+
bool should_set_parent_group_id = false;
int desired_parent_group_id = 0;
if (job_get_flag(j, JOB_CONTROL))
{
should_set_parent_group_id = true;
-
+
// PCA: I'm quite fuzzy on process groups,
// but I believe that the default value of 0
// means that the process becomes its own
@@ -388,13 +388,13 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
// in this case. So we want this to be 0 if j->pgid is 0.
desired_parent_group_id = j->pgid;
}
-
- /* Set the handling for job control signals back to the default. */
- bool reset_signal_handlers = true;
-
- /* Remove all signal blocks */
- bool reset_sigmask = true;
-
+
+ /* Set the handling for job control signals back to the default. */
+ bool reset_signal_handlers = true;
+
+ /* Remove all signal blocks */
+ bool reset_sigmask = true;
+
/* Set our flags */
short flags = 0;
if (reset_signal_handlers)
@@ -403,7 +403,7 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
flags |= POSIX_SPAWN_SETSIGMASK;
if (should_set_parent_group_id)
flags |= POSIX_SPAWN_SETPGROUP;
-
+
int err = 0;
if (! err)
err = posix_spawnattr_setflags(attr, flags);
@@ -418,16 +418,16 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
get_signals_with_handlers(&sigdefault);
err = posix_spawnattr_setsigdefault(attr, &sigdefault);
}
-
+
/* No signals blocked */
sigset_t sigmask;
sigemptyset(&sigmask);
if (! err && reset_sigmask)
err = posix_spawnattr_setsigmask(attr, &sigmask);
-
+
/* Make sure that our pipes don't use an fd that the redirection itself wants to use */
free_redirected_fds_from_pipes(j->io);
-
+
/* Close unused internal pipes */
std::vector<int> files_to_close;
get_unused_internal_pipes(files_to_close, j->io);
@@ -435,22 +435,22 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
{
err = posix_spawn_file_actions_addclose(actions, files_to_close.at(i));
}
-
+
for (size_t idx = 0; idx < j->io.size(); idx++)
{
const io_data_t *io = j->io.at(idx);
-
- if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
- {
- continue;
- }
-
- if( io->fd > 2 )
- {
- /* Make sure the fd used by this redirection is not used by e.g. a pipe. */
+
+ if( io->io_mode == IO_FD && io->fd == io->param1.old_fd )
+ {
+ continue;
+ }
+
+ if( io->fd > 2 )
+ {
+ /* Make sure the fd used by this redirection is not used by e.g. a pipe. */
// free_fd(io_chain, io->fd );
// PCA I don't think we need to worry about this. fd redirection is pretty uncommon anyways.
- }
+ }
switch (io->io_mode)
{
case IO_CLOSE:
@@ -459,141 +459,141 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil
err = posix_spawn_file_actions_addclose(actions, io->fd);
break;
}
-
+
case IO_FILE:
{
- if (! err)
+ if (! err)
err = posix_spawn_file_actions_addopen(actions, io->fd, io->filename_cstr, io->param2.flags /* mode */, OPEN_MASK);
break;
}
-
+
case IO_FD:
{
if (! err)
err = posix_spawn_file_actions_adddup2(actions, io->param1.old_fd /* from */, io->fd /* to */);
break;
}
-
- case IO_BUFFER:
- case IO_PIPE:
- {
+
+ case IO_BUFFER:
+ case IO_PIPE:
+ {
unsigned int write_pipe_idx = (io->is_input ? 0 : 1);
int from_fd = io->param1.pipe_fd[write_pipe_idx];
int to_fd = io->fd;
if (! err)
err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd);
-
- if( write_pipe_idx > 0 )
- {
- if (! err)
+
+ if( write_pipe_idx > 0 )
+ {
+ if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]);
if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[1]);
- }
- else
- {
- if (! err)
+ }
+ else
+ {
+ if (! err)
err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]);
- }
+ }
break;
}
}
}
-
+
/* Clean up on error */
if (err) {
posix_spawnattr_destroy(attr);
posix_spawn_file_actions_destroy(actions);
}
-
+
return ! err;
}
#endif //FISH_USE_POSIX_SPAWN
void safe_report_exec_error(int err, const char *actual_cmd, char **argv, char **envv)
{
- debug_safe( 0, "Failed to execute process '%s'. Reason:", actual_cmd );
-
- switch( err )
- {
-
- case E2BIG:
- {
- char sz1[128], sz2[128];
-
- long arg_max = -1;
-
- size_t sz = 0;
- char **p;
- for(p=argv; *p; p++)
- {
- sz += strlen(*p)+1;
- }
-
- for(p=envv; *p; p++)
- {
- sz += strlen(*p)+1;
- }
-
+ debug_safe( 0, "Failed to execute process '%s'. Reason:", actual_cmd );
+
+ switch( err )
+ {
+
+ case E2BIG:
+ {
+ char sz1[128], sz2[128];
+
+ long arg_max = -1;
+
+ size_t sz = 0;
+ char **p;
+ for(p=argv; *p; p++)
+ {
+ sz += strlen(*p)+1;
+ }
+
+ for(p=envv; *p; p++)
+ {
+ sz += strlen(*p)+1;
+ }
+
format_size_safe(sz1, sz);
- arg_max = sysconf( _SC_ARG_MAX );
-
- if( arg_max > 0 )
- {
+ arg_max = sysconf( _SC_ARG_MAX );
+
+ if( arg_max > 0 )
+ {
format_size_safe(sz2, sz);
debug_safe(0, "The total size of the argument and environment lists %s exceeds the operating system limit of %s.", sz1, sz2);
- }
- else
- {
- debug_safe( 0, "The total size of the argument and environment lists (%s) exceeds the operating system limit.", sz1);
- }
-
- debug_safe(0, "Try running the command again with fewer arguments.");
- break;
- }
-
- case ENOEXEC:
- {
+ }
+ else
+ {
+ debug_safe( 0, "The total size of the argument and environment lists (%s) exceeds the operating system limit.", sz1);
+ }
+
+ debug_safe(0, "Try running the command again with fewer arguments.");
+ break;
+ }
+
+ case ENOEXEC:
+ {
/* Hope strerror doesn't allocate... */
const char *err = strerror(errno);
debug_safe(0, "exec: %s", err);
-
- debug_safe(0, "The file '%s' is marked as an executable but could not be run by the operating system.", actual_cmd);
+
+ debug_safe(0, "The file '%s' is marked as an executable but could not be run by the operating system.", actual_cmd);
break;
- }
+ }
- case ENOENT:
- {
+ case ENOENT:
+ {
/* ENOENT is returned by exec() when the path fails, but also returned by posix_spawn if an open file action fails. These cases appear to be impossible to distinguish. We address this by not using posix_spawn for file redirections, so all the ENOENTs we find must be errors from exec(). */
char interpreter_buff[128] = {}, *interpreter;
interpreter = get_interpreter(actual_cmd, interpreter_buff, sizeof interpreter_buff);
- if( interpreter && 0 != access( interpreter, X_OK ) )
- {
- debug_safe(0, "The file '%s' specified the interpreter '%s', which is not an executable command.", actual_cmd, interpreter );
- }
- else
- {
- debug_safe(0, "The file '%s' does not exist or could not be executed.", actual_cmd);
- }
+ if( interpreter && 0 != access( interpreter, X_OK ) )
+ {
+ debug_safe(0, "The file '%s' specified the interpreter '%s', which is not an executable command.", actual_cmd, interpreter );
+ }
+ else
+ {
+ debug_safe(0, "The file '%s' does not exist or could not be executed.", actual_cmd);
+ }
break;
- }
+ }
- case ENOMEM:
- {
- debug_safe(0, "Out of memory");
+ case ENOMEM:
+ {
+ debug_safe(0, "Out of memory");
break;
- }
+ }
- default:
- {
+ default:
+ {
/* Hope strerror doesn't allocate... */
const char *err = strerror(errno);
debug_safe(0, "exec: %s", err);
-
- // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
+
+ // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd);
break;
- }
- }
+ }
+ }
}