/* * close a file */ static globus_result_t globus_l_xio_pipe_close( void * driver_specific_handle, void * attr, globus_xio_operation_t op) { xio_l_pipe_handle_t * handle; GlobusXIOName(globus_l_xio_pipe_close); GlobusXIOPipeDebugEnter(); handle = (xio_l_pipe_handle_t *) driver_specific_handle; globus_xio_system_file_destroy(handle->in_system); globus_xio_system_file_destroy(handle->out_system); globus_xio_system_file_close(handle->infd); globus_xio_system_file_close(handle->outfd); globus_xio_driver_finished_close(op, GLOBUS_SUCCESS); globus_l_xio_pipe_handle_destroy(handle); GlobusXIOPipeDebugExit(); return GLOBUS_SUCCESS; }
/* * close a file */ static globus_result_t globus_l_xio_popen_close( void * driver_specific_handle, void * attr, globus_xio_operation_t op) { xio_l_popen_handle_t * handle; GlobusXIOName(globus_l_xio_popen_close); GlobusXIOPOpenDebugEnter(); handle = (xio_l_popen_handle_t *) driver_specific_handle; handle->close_op = op; globus_xio_system_file_destroy(handle->in_system); globus_xio_system_file_close(handle->infd); #if !defined(USE_SOCKET_PAIR) globus_xio_system_file_close(handle->outfd); globus_xio_system_file_destroy(handle->out_system); #endif if(globus_xio_driver_operation_is_blocking(op)) { globus_l_popen_waitpid(handle, 0); } else { globus_l_popen_waitpid(handle, WNOHANG); } GlobusXIOPOpenDebugExit(); return GLOBUS_SUCCESS; }
static void globus_l_popen_waitpid( xio_l_popen_handle_t * handle, int opts) { globus_result_t result = GLOBUS_SUCCESS; int status; int rc; globus_reltime_t delay; GlobusXIOName(globus_l_popen_waitpid); #ifdef WIN32 result = GlobusXIOErrorSystemResource("not available for windows"); #else rc = waitpid(handle->pid, &status, opts); if(rc > 0) { /* if program exited normally, but with a nonzero code OR * program exited by signal, and we didn't signal it */ if(((WIFEXITED(status) && WEXITSTATUS(status) != 0) || (WIFSIGNALED(status) && handle->kill_state != GLOBUS_L_XIO_POPEN_NONE)) && !handle->ignore_program_errors) { /* read programs stderr and dump it to an error result */ globus_size_t nbytes = 0; globus_xio_iovec_t iovec; char buf[8192]; iovec.iov_base = buf; iovec.iov_len = sizeof(buf) - 1; result = globus_xio_system_file_read( handle->err_system, 0, &iovec, 1, 0, &nbytes); buf[nbytes] = 0; if(WIFEXITED(status)) { result = globus_error_put( globus_error_construct_error( GLOBUS_XIO_MODULE, GLOBUS_NULL, GLOBUS_XIO_ERROR_SYSTEM_ERROR, __FILE__, _xio_name, __LINE__, _XIOSL("popened program exited with an error " "(exit code: %d):\n%s"), WEXITSTATUS(status), buf)); } else { result = globus_error_put( globus_error_construct_error( GLOBUS_XIO_MODULE, GLOBUS_NULL, GLOBUS_XIO_ERROR_SYSTEM_ERROR, __FILE__, _xio_name, __LINE__, _XIOSL("popened program was terminated by a signal" "(sig: %d)"), WTERMSIG(status))); } } globus_xio_system_file_close(handle->errfd); globus_xio_system_file_destroy(handle->err_system); globus_xio_driver_finished_close(handle->close_op, result); globus_l_xio_popen_handle_destroy(handle); } else if(rc < 0 || opts == 0) { /* If the errno is ECHILD, either some other thread or part of the * program called wait and got this pid's exit status, or sigaction * with SA_NOCLDWAIT prevented the process from becoming a zombie. Not * really an error case. */ if (errno != ECHILD) { result = GlobusXIOErrorSystemError("waitpid", errno); } globus_xio_system_file_close(handle->errfd); globus_xio_system_file_destroy(handle->err_system); globus_xio_driver_finished_close(handle->close_op, result); globus_l_xio_popen_handle_destroy(handle); } else { handle->wait_count++; if(handle->canceled) { switch(handle->kill_state) { case GLOBUS_L_XIO_POPEN_NONE: if(handle->wait_count > 5000 / GLOBUS_L_XIO_POPEN_WAITPID_DELAY) { handle->kill_state = GLOBUS_L_XIO_POPEN_TERM; kill(handle->pid, SIGTERM); } break; case GLOBUS_L_XIO_POPEN_TERM: if(handle->wait_count > 15000 / GLOBUS_L_XIO_POPEN_WAITPID_DELAY) { handle->kill_state = GLOBUS_L_XIO_POPEN_KILL; kill(handle->pid, SIGKILL); } break; default: break; } } GlobusTimeReltimeSet(delay, 0, GLOBUS_L_XIO_POPEN_WAITPID_DELAY); globus_callback_register_oneshot( NULL, &delay, globus_l_xio_popen_close_oneshot, handle); } #endif GlobusXIOPOpenDebugExit(); }