diff options
author | Łukasz Niemier <lukasz@niemier.pl> | 2012-11-18 11:23:22 +0100 |
---|---|---|
committer | Łukasz Niemier <lukasz@niemier.pl> | 2012-11-18 11:23:22 +0100 |
commit | 47df1ae40adecd0a02fc7dd06ab0745cb18c3fe0 (patch) | |
tree | 13bf3e8fdcae60fdfb5fa5e26c95818dc7a49790 /postfork.cpp | |
parent | b79854ad1aa814d9d35d76a1929b4726fa4bffa5 (diff) |
Remove trailing whitespaces and change tabs to spaces
Diffstat (limited to 'postfork.cpp')
-rw-r--r-- | postfork.cpp | 640 |
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; - } - } + } + } } |