globus_result_t globus_xio_system_socket_getsockopt( globus_xio_system_socket_t socket, int level, int optname, void * optval, socklen_t * optlen) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_getsockopt); GlobusXIOSystemDebugEnterFD(socket); if(getsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError("getsockopt", WSAGetLastError()); goto error_getsockopt; } GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_getsockopt: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_system_socket_create( globus_xio_system_socket_t * sock, int domain, int type, int protocol) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_create); *sock = INVALID_SOCKET; GlobusXIOSystemDebugEnter(); *sock = socket(domain, type, protocol); if(*sock == INVALID_SOCKET) { result = GlobusXIOErrorSystemError("socket", WSAGetLastError()); goto error_socket; } /* all handles created by me are closed on exec */ SetHandleInformation((HANDLE)*sock, HANDLE_FLAG_INHERIT, 0); GlobusXIOSystemDebugExitFD(*sock); return GLOBUS_SUCCESS; error_socket: GlobusXIOSystemDebugExitWithErrorFD(*sock); return result; }
globus_result_t globus_i_xio_system_try_sendto( globus_xio_system_socket_t fd, void * buf, globus_size_t buflen, int flags, const globus_sockaddr_t * to, globus_size_t * nbytes) { globus_ssize_t rc = 0; globus_result_t result; GlobusXIOName(globus_i_xio_system_try_sendto); GlobusXIOSystemDebugEnterFD(fd); if(buflen) { do { rc = sendto( fd, buf, buflen, flags, (struct sockaddr *) to, GlobusLibcSockaddrLen(to)); GlobusXIOSystemUpdateErrno(); } while(rc < 0 && errno == EINTR); if(rc < 0) { if(GlobusLXIOSystemWouldBlock(errno)) { rc = 0; } else { result = GlobusXIOErrorSystemError("sendto", errno); goto error_errno; } } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Wrote %d bytes\n", _xio_name, rc)); GlobusXIOSystemDebugRawBuffer(rc, buf); } *nbytes = rc; GlobusXIOSystemDebugExitFD(fd); return GLOBUS_SUCCESS; error_errno: *nbytes = 0; GlobusXIOSystemDebugExitWithErrorFD(fd); return result; }
globus_result_t globus_i_xio_system_try_readv( globus_xio_system_file_t fd, const globus_xio_iovec_t * iov, int iovc, globus_size_t * nbytes) { globus_ssize_t rc; globus_result_t result; GlobusXIOName(globus_i_xio_system_try_readv); GlobusXIOSystemDebugEnterFD(fd); do { #ifdef HAVE_READV rc = readv(fd, iov, (iovc > globus_l_xio_iov_max) ? globus_l_xio_iov_max : iovc); #else rc = read(fd, iov[0].iov_base,iov[0].iov_len); #endif GlobusXIOSystemUpdateErrno(); } while(rc < 0 && errno == EINTR); if(rc < 0) { if(GlobusLXIOSystemWouldBlock(errno)) { rc = 0; } else { result = GlobusXIOErrorSystemError("readv", errno); goto error_errno; } } else if(rc == 0) { result = GlobusXIOErrorEOF(); goto error_eof; } *nbytes = rc; GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Read %d bytes\n", _xio_name, rc)); GlobusXIOSystemDebugRawIovec(rc, iov); GlobusXIOSystemDebugExitFD(fd); return GLOBUS_SUCCESS; error_errno: error_eof: *nbytes = 0; GlobusXIOSystemDebugExitWithErrorFD(fd); return result; }
globus_result_t globus_i_xio_system_try_recv( globus_xio_system_socket_t fd, void * buf, globus_size_t buflen, int flags, globus_size_t * nbytes) { globus_ssize_t rc = 0; globus_result_t result; GlobusXIOName(globus_i_xio_system_try_recv); GlobusXIOSystemDebugEnterFD(fd); if(buflen) { do { rc = recv(fd, buf, buflen, flags); GlobusXIOSystemUpdateErrno(); } while(rc < 0 && errno == EINTR); if(rc < 0) { if(GlobusLXIOSystemWouldBlock(errno)) { rc = 0; } else { result = GlobusXIOErrorSystemError("recv", errno); goto error_errno; } } else if(rc == 0) { result = GlobusXIOErrorEOF(); goto error_eof; } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Read %d bytes\n", _xio_name, rc)); GlobusXIOSystemDebugRawBuffer(rc, buf); } *nbytes = rc; GlobusXIOSystemDebugExitFD(fd); return GLOBUS_SUCCESS; error_errno: error_eof: *nbytes = 0; GlobusXIOSystemDebugExitWithErrorFD(fd); return result; }
globus_result_t globus_i_xio_system_try_read( globus_xio_system_file_t fd, void * buf, globus_size_t buflen, globus_size_t * nbytes) { globus_ssize_t rc = 0; globus_result_t result; GlobusXIOName(globus_i_xio_system_try_read); GlobusXIOSystemDebugEnterFD(fd); /* calls to this with buflen == 0 are requesting select only */ if(buflen) { do { rc = read(fd, buf, buflen); GlobusXIOSystemUpdateErrno(); } while(rc < 0 && errno == EINTR); if(rc < 0) { if(GlobusLXIOSystemWouldBlock(errno)) { rc = 0; } else { result = GlobusXIOErrorSystemError("read", errno); goto error_errno; } } else if(rc == 0) /* what about UDP? */ { result = GlobusXIOErrorEOF(); goto error_eof; } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Read %d bytes (buflen = %d)\n", _xio_name, rc, buflen)); GlobusXIOSystemDebugRawBuffer(rc, buf); } *nbytes = rc; GlobusXIOSystemDebugExitFD(fd); return GLOBUS_SUCCESS; error_errno: error_eof: *nbytes = 0; GlobusXIOSystemDebugExitWithErrorFD(fd); return result; }
globus_result_t globus_xio_system_socket_register_connect( globus_xio_operation_t op, globus_xio_system_socket_handle_t handle, globus_sockaddr_t * addr, globus_xio_system_callback_t callback, void * user_arg) { globus_result_t result; int error; globus_i_xio_system_op_info_t * op_info; GlobusXIOName(globus_xio_system_socket_register_connect); GlobusXIOSystemDebugEnterFD(handle->socket); if(connect( handle->socket, (const struct sockaddr *) addr, GlobusLibcSockaddrLen(addr)) == SOCKET_ERROR && (error = WSAGetLastError()) != WSAEWOULDBLOCK) { result = GlobusXIOErrorSystemError("connect", error); goto error_connect; } GlobusIXIOSystemAllocOperation(op_info); if(!op_info) { result = GlobusXIOErrorMemory("op_info"); goto error_op_info; } op_info->type = GLOBUS_I_XIO_SYSTEM_OP_CONNECT; op_info->state = GLOBUS_I_XIO_SYSTEM_OP_NEW; op_info->op = op; op_info->handle = handle; op_info->user_arg = user_arg; op_info->sop.non_data.callback = callback; result = globus_l_xio_win32_socket_register_write(handle, op_info); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_win32_socket_register_write", result); goto error_register; } GlobusXIOSystemDebugExitFD(handle->socket); return GLOBUS_SUCCESS; error_register: GlobusIXIOSystemFreeOperation(op_info); error_op_info: error_connect: GlobusXIOSystemDebugExitWithErrorFD(handle->socket); return result; }
static globus_result_t globus_l_xio_win32_blocking_init( globus_l_xio_win32_blocking_info_t ** u_blocking_info) { globus_l_xio_win32_blocking_info_t * blocking_info; globus_result_t result; GlobusXIOName(globus_l_xio_win32_blocking_init); GlobusXIOSystemDebugEnter(); blocking_info = (globus_l_xio_win32_blocking_info_t *) globus_calloc(1, sizeof(globus_l_xio_win32_blocking_info_t)); if(!blocking_info) { result = GlobusXIOErrorMemory("blocking_info"); goto error_info; } blocking_info->event = CreateEvent(0, FALSE, FALSE, 0); if(blocking_info->event == 0) { result = GlobusXIOErrorSystemError( "CreateEvent", GetLastError()); goto error_create; } *u_blocking_info = blocking_info; GlobusXIOSystemDebugExit(); return GLOBUS_SUCCESS; error_create: globus_free(blocking_info); error_info: *u_blocking_info = 0; GlobusXIOSystemDebugExitWithError(); return result; }
globus_result_t globus_xio_system_socket_close( globus_xio_system_socket_t socket) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_close); GlobusXIOSystemDebugEnterFD(socket); if(closesocket(socket) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError("closesocket", WSAGetLastError()); goto error_close; } GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_close: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_system_socket_listen( globus_xio_system_socket_t socket, int backlog) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_listen); GlobusXIOSystemDebugEnterFD(socket); if(listen(socket, backlog) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError("listen", WSAGetLastError()); goto error_listen; } GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_listen: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_system_socket_connect( globus_xio_system_socket_t socket, const struct sockaddr * addr, socklen_t addrlen) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_connect); GlobusXIOSystemDebugEnterFD(socket); if(connect(socket, addr, addrlen) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError("connect", WSAGetLastError()); goto error_connect; } GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_connect: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_system_socket_getpeername( globus_xio_system_socket_t socket, struct sockaddr * name, socklen_t * namelen) { globus_result_t result; GlobusXIOName(globus_xio_system_socket_getpeername); GlobusXIOSystemDebugEnterFD(socket); if(getpeername(socket, name, namelen) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError("getpeername", WSAGetLastError()); goto error_getpeername; } GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_getpeername: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
globus_result_t globus_xio_system_socket_init( globus_xio_system_socket_handle_t * uhandle, globus_xio_system_socket_t socket, globus_xio_system_type_t type) { globus_result_t result; globus_l_xio_win32_socket_t * handle; unsigned long flag; GlobusXIOName(globus_xio_system_socket_init); GlobusXIOSystemDebugEnterFD(socket); handle = (globus_l_xio_win32_socket_t *) globus_calloc(1, sizeof(globus_l_xio_win32_socket_t)); if(!handle) { result = GlobusXIOErrorMemory("handle"); goto error_alloc; } handle->socket = socket; win32_mutex_init(&handle->lock, 0); handle->ready_events = FD_READ; /* to avoid winsock fd_close bug */ handle->event = WSACreateEvent(); if(handle->event == 0) { result = GlobusXIOErrorSystemError( "WSACreateEvent", WSAGetLastError()); goto error_create; } flag = 1; if(ioctlsocket(socket, FIONBIO, &flag) == SOCKET_ERROR) { result = GlobusXIOErrorSystemError( "ioctlsocket", WSAGetLastError()); goto error_ioctl; } result = globus_i_xio_win32_event_register( &handle->event_entry, handle->event, globus_l_xio_win32_socket_event_cb, handle); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_i_xio_win32_event_register", result); goto error_register; } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Registered event handle=%lu\n", _xio_name, (unsigned long) handle->event)); *uhandle = handle; GlobusXIOSystemDebugExitFD(socket); return GLOBUS_SUCCESS; error_register: flag = 0; ioctlsocket(socket, FIONBIO, &flag); error_ioctl: WSACloseEvent(handle->event); error_create: win32_mutex_destroy(&handle->lock); globus_free(handle); error_alloc: GlobusXIOSystemDebugExitWithErrorFD(socket); return result; }
/* must be safe to call from win32 thread */ static void globus_l_xio_win32_socket_handle_write( globus_l_xio_win32_socket_t * handle, globus_i_xio_system_op_info_t * write_info) { globus_size_t nbytes; globus_result_t result; GlobusXIOName(globus_l_xio_win32_socket_handle_write); GlobusXIOSystemDebugEnterFD(handle->socket); result = GLOBUS_SUCCESS; if(write_info->op) { globus_xio_operation_refresh_timeout(write_info->op); } switch(write_info->type) { case GLOBUS_I_XIO_SYSTEM_OP_CONNECT: { int err; globus_socklen_t errlen; errlen = sizeof(err); if(getsockopt( handle->socket, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen) == SOCKET_ERROR) { err = WSAGetLastError(); } if(err) { result = GlobusXIOErrorSystemError("connect", err); } } break; case GLOBUS_I_XIO_SYSTEM_OP_WRITE: /* we loop repeatedly here to use up all available space until * the write would return EWOULDBLOCK. at that time, we'll get * another event to land us back here */ do { result = globus_i_xio_system_socket_try_write( handle->socket, write_info->sop.data.iov, write_info->sop.data.iovc, write_info->sop.data.flags, write_info->sop.data.addr, &nbytes); if(result == GLOBUS_SUCCESS) { if(nbytes > 0) { write_info->nbytes += nbytes; GlobusIXIOUtilAdjustIovec( write_info->sop.data.iov, write_info->sop.data.iovc, nbytes); } else if(write_info->sop.data.iovc > 0 && write_info->sop.data.iov[0].iov_len > 0) { /* we consumed write event */ handle->ready_events &= ~FD_WRITE; } } } while(nbytes > 0 && write_info->nbytes < write_info->waitforbytes); break; default: globus_assert(0 && "Unexpected type for write operation"); return; break; } if(result != GLOBUS_SUCCESS) { write_info->error = globus_error_get(result); } /* always true for connect operations */ if(write_info->nbytes >= write_info->waitforbytes || result != GLOBUS_SUCCESS) { write_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE; } GlobusXIOSystemDebugExitFD(handle->socket); }
globus_result_t globus_i_xio_system_try_sendmsg( globus_xio_system_socket_t fd, struct msghdr * msghdr, int flags, globus_size_t * nbytes) { globus_ssize_t rc; globus_result_t result; GlobusXIOName(globus_i_xio_system_try_sendmsg); GlobusXIOSystemDebugEnterFD(fd); #ifdef WIN32 { DWORD sent = 0; rc = WSASendTo( fd, (WSABUF *) msghdr->msg_iov, msghdr->msg_iovlen, &sent, flags, msghdr->msg_name, msghdr->msg_namelen, 0, 0); if(rc != 0) { GlobusXIOSystemUpdateErrno(); rc = -1; } else { rc = sent; } } #elif defined(HAVE_SENDMSG) { globus_size_t orig_iovc; orig_iovc = msghdr->msg_iovlen; msghdr->msg_iovlen = (orig_iovc > globus_l_xio_iov_max) ? globus_l_xio_iov_max : orig_iovc; do { rc = sendmsg(fd, msghdr, flags); GlobusXIOSystemUpdateErrno(); } while(rc < 0 && errno == EINTR); msghdr->msg_iovlen = orig_iovc; } #else { /* XXX this is not an acceptable work around for udp sockets */ do { if (msghdr->msg_name) { rc = sendto( fd, msghdr->msg_iov[0].iov_base, msghdr->msg_iov[0].iov_len, flags, (struct sockaddr *) msghdr->msg_name, msghdr->msg_namelen); } else { rc = send( fd, msghdr->msg_iov[0].iov_base, msghdr->msg_iov[0].iov_len, flags); } GlobusXIOSystemUpdateErrno(); } while (rc < 0 && errno == EINTR); } #endif if(rc < 0) { if(GlobusLXIOSystemWouldBlock(errno)) { rc = 0; } else { result = GlobusXIOErrorSystemError("sendmsg", errno); goto error_errno; } } *nbytes = rc; GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_DATA, ("[%s] Wrote %d bytes\n", _xio_name, rc)); GlobusXIOSystemDebugRawIovec(rc, msghdr->msg_iov); GlobusXIOSystemDebugExitFD(fd); return GLOBUS_SUCCESS; error_errno: *nbytes = 0; GlobusXIOSystemDebugExitWithErrorFD(fd); return result; }
/* * open a file */ static globus_result_t globus_l_xio_popen_open( const globus_xio_contact_t * contact_info, void * driver_link, void * driver_attr, globus_xio_operation_t op) { int rc; int s_fds[2]; int infds[2]; int outfds[2]; int errfds[2]; xio_l_popen_handle_t * handle; const xio_l_popen_attr_t * attr; globus_result_t result; GlobusXIOName(globus_l_xio_popen_open); GlobusXIOPOpenDebugEnter(); #ifdef WIN32 result = GlobusXIOErrorSystemResource("not available for windows"); #else attr = (const xio_l_popen_attr_t *) driver_attr ? driver_attr : &xio_l_popen_attr_default; /* check that program exists and is exec=able first */ rc = access(attr->program_name, R_OK | X_OK); if(rc != 0) { result = GlobusXIOErrorSystemError("access check", errno); goto error_handle; } result = globus_l_xio_popen_handle_init(&handle); if(result != GLOBUS_SUCCESS) { result = GlobusXIOErrorWrapFailed( "globus_l_xio_popen_handle_init", result); goto error_handle; } handle->ignore_program_errors = attr->ignore_program_errors; handle->use_blocking_io = attr->use_blocking_io; # if defined(USE_SOCKET_PAIR) { rc = socketpair(AF_UNIX, SOCK_STREAM, 0, s_fds); if(rc != 0) { result = GlobusXIOErrorSystemError("socketpair", errno); goto error_in_pipe; } /* trick the rest of the code into thinking it is using pipe */ outfds[0] = s_fds[0]; outfds[1] = s_fds[1]; infds[0] = s_fds[0]; infds[1] = s_fds[1]; } # else { rc = pipe(infds); if(rc != 0) { result = GlobusXIOErrorSystemError("pipe", errno); goto error_in_pipe; } rc = pipe(outfds); if(rc != 0) { result = GlobusXIOErrorSystemError("pipe", errno); goto error_out_pipe; } } # endif rc = pipe(errfds); if(rc != 0) { result = GlobusXIOErrorSystemError("pipe", errno); goto error_err_pipe; } fcntl(errfds[0], F_SETFL, O_NONBLOCK); fcntl(errfds[1], F_SETFL, O_NONBLOCK); handle->pid = fork(); if(handle->pid < 0) { result = GlobusXIOErrorSystemError("fork", errno); goto error_fork; } else if(handle->pid == 0) { globus_l_xio_popen_child(attr, contact_info, infds, outfds, errfds); } # if defined(USE_SOCKET_PAIR) { handle->infd = s_fds[0]; handle->outfd = s_fds[0]; result = globus_l_xio_popen_init_child_pipe( handle->infd, &handle->in_system); if(result != GLOBUS_SUCCESS) { goto error_init; } handle->out_system = handle->in_system; close(s_fds[1]); } # else { handle->infd = infds[0]; handle->outfd = outfds[1]; result = globus_l_xio_popen_init_child_pipe( handle->outfd, &handle->out_system); if(result != GLOBUS_SUCCESS) { goto error_init; } result = globus_l_xio_popen_init_child_pipe( handle->infd, &handle->in_system); if(result != GLOBUS_SUCCESS) { goto error_init; } close(outfds[0]); close(infds[1]); } # endif handle->errfd = errfds[0]; result = globus_l_xio_popen_init_child_pipe( handle->errfd, &handle->err_system); if(result != GLOBUS_SUCCESS) { goto error_init; } close(errfds[1]); globus_xio_driver_finished_open(handle, op, GLOBUS_SUCCESS); GlobusXIOPOpenDebugExit(); return GLOBUS_SUCCESS; error_init: error_fork: close(errfds[0]); close(errfds[1]); # if defined(USE_SOCKET_PAIR) error_err_pipe: close(s_fds[0]); close(s_fds[1]); # else error_err_pipe: close(outfds[0]); close(outfds[1]); error_out_pipe: close(infds[0]); close(infds[1]); # endif error_in_pipe: globus_l_xio_popen_handle_destroy(handle); error_handle: #endif GlobusXIOPOpenDebugExitWithError(); return result; }
/* must be safe to call from win32 thread */ static void globus_l_xio_win32_socket_handle_read( globus_l_xio_win32_socket_t * handle, globus_i_xio_system_op_info_t * read_info) { globus_size_t nbytes; globus_result_t result; GlobusXIOName(globus_l_xio_win32_socket_handle_read); GlobusXIOSystemDebugEnterFD(handle->socket); result = GLOBUS_SUCCESS; if(read_info->op) { globus_xio_operation_refresh_timeout(read_info->op); } GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] In globus_l_xio_win32_socket_handle_read fd=%lu, read_info->type=%d\n", _xio_name, (unsigned long)handle->socket, (int) read_info->type)); switch(read_info->type) { case GLOBUS_I_XIO_SYSTEM_OP_ACCEPT: { SOCKET new_fd; new_fd = accept(handle->socket, 0, 0); if(new_fd == INVALID_SOCKET) { int error = WSAGetLastError(); if(error != WSAECONNRESET && error != WSAEWOULDBLOCK) { char errbuf[64]; sprintf(errbuf, "accept, fd=%ld, error=%d", (long) handle->socket, error); result = GlobusXIOErrorSystemError(errbuf, error); GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Tried to accept new connection on fd=%lu, %s\n", _xio_name, (unsigned long)handle->socket, errbuf)); } else { char errbuf[64]; sprintf(errbuf, "accept, fd=%ld, error=%d", (long) handle->socket, error); GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Tried to accept new connection on fd=%lu, %s\n", _xio_name, (unsigned long)handle->socket, errbuf)); } } else { unsigned long flag = 0; /* clear inherited attrs */ WSAEventSelect(new_fd, 0, 0); ioctlsocket(new_fd, FIONBIO, &flag); *read_info->sop.non_data.out_fd = new_fd; read_info->nbytes++; GlobusXIOSystemDebugPrintf( GLOBUS_I_XIO_SYSTEM_DEBUG_INFO, ("[%s] Accepted new connection on fd=%lu, fd=%lu\n", _xio_name, (unsigned long)handle->socket, (unsigned long)new_fd)); } } break; case GLOBUS_I_XIO_SYSTEM_OP_READ: /* we loop repeatedly here to read all available data until * the read would return EWOULDBLOCK. at that time, we'll get * another event to land us back here. * (This looping is necessary to work around a winsock bug where we * aren't notified of the peer closing the connection on short lived * connections) */ do { result = globus_i_xio_system_socket_try_read( handle->socket, read_info->sop.data.iov, read_info->sop.data.iovc, read_info->sop.data.flags, read_info->sop.data.addr, &nbytes); if(result == GLOBUS_SUCCESS) { if(nbytes > 0) { read_info->nbytes += nbytes; GlobusIXIOUtilAdjustIovec( read_info->sop.data.iov, read_info->sop.data.iovc, nbytes); } else if(read_info->sop.data.iovc > 0 && read_info->sop.data.iov[0].iov_len > 0) { /* we consumed read event */ handle->ready_events &= ~FD_READ; } } } while(nbytes > 0 && read_info->nbytes < read_info->waitforbytes); break; default: globus_assert(0 && "Unexpected type for read operation"); return; break; } if(result != GLOBUS_SUCCESS) { read_info->error = globus_error_get(result); } /* always true for accept operations */ if(read_info->nbytes >= read_info->waitforbytes || result != GLOBUS_SUCCESS) { read_info->state = GLOBUS_I_XIO_SYSTEM_OP_COMPLETE; } GlobusXIOSystemDebugExitFD(handle->socket); }
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(); }