diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2012-11-18 16:30:30 -0800 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2012-11-18 16:30:30 -0800 |
commit | 9992b8eb0e3366ff8a3948aa0b66a19c3c12c737 (patch) | |
tree | 6dda0fef85812016fbba9ea067c9d586092b506d /postfork.cpp | |
parent | bab69f26724028d16054a3daf5c78aad7c67bb2d (diff) |
Apply new indentation, brace, and whitespace style
Diffstat (limited to 'postfork.cpp')
-rw-r--r-- | postfork.cpp | 592 |
1 files changed, 298 insertions, 294 deletions
diff --git a/postfork.cpp b/postfork.cpp index 2609831f..32dd4455 100644 --- a/postfork.cpp +++ b/postfork.cpp @@ -42,21 +42,21 @@ 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 set_child_group(job_t *j, process_t *p, int print_errors) { - int res = 0; + int res = 0; - if( job_get_flag( j, JOB_CONTROL ) ) - { - if (!j->pgid) + if (job_get_flag(j, JOB_CONTROL)) { - j->pgid = p->pid; - } + if (!j->pgid) + { + j->pgid = p->pid; + } - if( setpgid (p->pid, j->pgid) ) - { - if( getpgid( p->pid) != j->pgid && print_errors ) - { + 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]; @@ -64,41 +64,41 @@ int set_child_group( job_t *j, process_t *p, int print_errors ) 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(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; - } + 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(); } - } - else - { - j->pgid = getpid(); - } - - if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) ) - { - if( tcsetpgrp (0, j->pgid) && print_errors ) + + 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. */ @@ -135,15 +135,15 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain) replacement_fd = dup(fd_to_free); if (replacement_fd == -1 && errno != EINTR) { - debug_safe_int( 1, FD_ERROR, fd_to_free ); - wperror( L"dup" ); + debug_safe_int(1, FD_ERROR, fd_to_free); + wperror(L"dup"); FATAL_EXIT(); } } possible_conflict->param1.pipe_fd[k] = replacement_fd; } } - } + } } @@ -159,152 +159,152 @@ static void free_redirected_fds_from_pipes(io_chain_t &io_chain) \return 0 on sucess, -1 on failiure */ -static int handle_child_io( 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++) - { - io_data_t *io = io_chain.at(idx); - int tmp; - - if( io->io_mode == IO_FD && io->fd == io->param1.old_fd ) + for (size_t idx = 0; idx < io_chain.size(); idx++) { - continue; - } + io_data_t *io = io_chain.at(idx); + int tmp; - switch( io->io_mode ) - { - case IO_CLOSE: - { - if( close(io->fd) ) + if (io->io_mode == IO_FD && io->fd == io->param1.old_fd) { - debug_safe_int( 0, "Failed to close file descriptor %s", io->fd ); - wperror( L"close" ); + continue; } - 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 ) + switch (io->io_mode) { - 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) + case IO_CLOSE: { - /* - 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 ); + if (close(io->fd)) + { + debug_safe_int(0, "Failed to close file descriptor %s", io->fd); + wperror(L"close"); + } + break; } - 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 ) + case IO_FILE: { - debug_safe_int( 1, FD_ERROR, io->fd ); - wperror( L"dup2" ); - return -1; + // 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; } - 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); -/* - 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 ) + + case IO_FD: { - debug_safe( 1, LOCAL_PIPE_ERROR ); - perror( "dup2" ); - return -1; + /* + 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; } - 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; - } + 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); + /* + 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 (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; + return 0; } -int setup_child_process( job_t *j, process_t *p ) +int setup_child_process(job_t *j, process_t *p) { - bool ok=true; + bool ok=true; - if( p ) - { - ok = (0 == set_child_group( j, p, 1 )); - } + if (p) + { + ok = (0 == set_child_group(j, p, 1)); + } - if( ok ) - { - ok = (0 == handle_child_io( j->io )); - if( p != 0 && ! ok ) + if (ok) { - exit_without_destructors( 1 ); + 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(); - } + /* Set the handling for job control signals back to the default. */ + if (ok) + { + signal_reset_handlers(); + } - /* Remove all signal blocks */ - signal_unblock(); + /* Remove all signal blocks */ + signal_unblock(); - return ok ? 0 : -1; + return ok ? 0 : -1; } int g_fork_count = 0; @@ -319,46 +319,47 @@ pid_t execute_fork(bool wait_for_threads_to_die) { ASSERT_IS_MAIN_THREAD(); - if (wait_for_threads_to_die) { + 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) + for (i=0; i<FORK_LAPS; i++) { - return pid; - } + pid = fork(); + if (pid >= 0) + { + return pid; + } - if( errno != EAGAIN ) - { - break; - } + if (errno != EAGAIN) + { + break; + } - pollint.tv_sec = 0; - pollint.tv_nsec = FORK_SLEEP_TIME; + 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 ); + /* + 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(); + debug_safe(0, FORK_ERROR); + wperror(L"fork"); + FATAL_EXIT(); return 0; } @@ -366,11 +367,13 @@ pid_t execute_fork(bool wait_for_threads_to_die) bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_file_actions_t *actions, job_t *j, process_t *p) { /* Initialize the output */ - if (posix_spawnattr_init(attr) != 0) { + if (posix_spawnattr_init(attr) != 0) + { return false; } - if (posix_spawn_file_actions_init(actions) != 0) { + if (posix_spawn_file_actions_init(actions) != 0) + { posix_spawnattr_destroy(attr); return false; } @@ -389,11 +392,11 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil desired_parent_group_id = j->pgid; } - /* Set the handling for job control signals back to the default. */ - bool reset_signal_handlers = 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; + /* Remove all signal blocks */ + bool reset_sigmask = true; /* Set our flags */ short flags = 0; @@ -440,70 +443,71 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil { const io_data_t *io = j->io.at(idx); - if( io->io_mode == IO_FD && io->fd == io->param1.old_fd ) - { - continue; - } + 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->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: - { - if (! err) - err = posix_spawn_file_actions_addclose(actions, io->fd); - break; - } + case IO_CLOSE: + { + if (! err) + err = posix_spawn_file_actions_addclose(actions, io->fd); + break; + } - case IO_FILE: - { - if (! err) - err = posix_spawn_file_actions_addopen(actions, io->fd, io->filename_cstr, io->param2.flags /* mode */, OPEN_MASK); - break; - } + case IO_FILE: + { + 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_FD: + 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) - err = posix_spawn_file_actions_adddup2(actions, io->param1.old_fd /* from */, io->fd /* to */); - break; + 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]); } - - 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; + else + { if (! err) - err = posix_spawn_file_actions_adddup2(actions, from_fd, to_fd); - + err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]); - 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) - err = posix_spawn_file_actions_addclose(actions, io->param1.pipe_fd[0]); - - } - break; } + break; + } } } /* Clean up on error */ - if (err) { + if (err) + { posix_spawnattr_destroy(attr); posix_spawn_file_actions_destroy(actions); } @@ -514,86 +518,86 @@ bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr, posix_spawn_fil 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 ); + debug_safe(0, "Failed to execute process '%s'. Reason:", actual_cmd); - switch( err ) - { + 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 ) - { - 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; + 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) + { + 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: { - /* Hope strerror doesn't allocate... */ - const char *err = strerror(errno); - debug_safe(0, "exec: %s", err); + /* 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); - break; + 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: { - /* 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); - } - break; + /* 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); + } + break; } case ENOMEM: { - debug_safe(0, "Out of memory"); - break; + debug_safe(0, "Out of memory"); + break; } default: { - /* Hope strerror doesn't allocate... */ - const char *err = strerror(errno); - debug_safe(0, "exec: %s", err); + /* 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); - break; + // debug(0, L"The file '%ls' is marked as an executable but could not be run by the operating system.", p->actual_cmd); + break; + } } - } } |