rbb 99/11/15 11:50:48
Modified: src/lib/apr/network_io/unix sendrecv.c sockopt.c src/modules/mpm/dexter dexter.c src/modules/mpm/mpmt_pthread mpmt_pthread.c src/modules/mpm/prefork prefork.c src/os/unix iol_socket.c iol_socket.h Log: Moving Unix socket IOL's to use APR. Also fixed a small bug in ap_recv. We should NEVER return a status of APR_EAGAIN and say -1 bytes read. This can cause some strange bugs. Revision Changes Path 1.5 +4 -0 apache-2.0/src/lib/apr/network_io/unix/sendrecv.c Index: sendrecv.c =================================================================== RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sendrecv.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- sendrecv.c 1999/11/10 15:49:55 1.4 +++ sendrecv.c 1999/11/15 19:49:51 1.5 @@ -169,6 +169,10 @@ } while (rv == -1 && errno == EINTR); } } + else if (rv == -1 && errno == EAGAIN && sock->timeout == 0) { + (*len) = 0; + return errno; + } (*len) = rv; return APR_SUCCESS; } 1.13 +3 -0 apache-2.0/src/lib/apr/network_io/unix/sockopt.c Index: sockopt.c =================================================================== RCS file: /home/cvs/apache-2.0/src/lib/apr/network_io/unix/sockopt.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- sockopt.c 1999/11/10 15:49:55 1.12 +++ sockopt.c 1999/11/15 19:49:54 1.13 @@ -176,6 +176,9 @@ } if (opt & APR_SO_TIMEOUT) { sock->timeout = on; + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) { + return stat; + } } return APR_SUCCESS; } 1.52 +1 -1 apache-2.0/src/modules/mpm/dexter/dexter.c Index: dexter.c =================================================================== RCS file: /home/cvs/apache-2.0/src/modules/mpm/dexter/dexter.c,v retrieving revision 1.51 retrieving revision 1.52 diff -u -r1.51 -r1.52 --- dexter.c 1999/10/30 01:49:53 1.51 +++ dexter.c 1999/11/15 19:50:05 1.52 @@ -750,7 +750,7 @@ } sock_disable_nagle(csd); - iol = unix_attach_socket(csd); + iol = unix_attach_socket(sock); if (iol == NULL) { if (errno == EBADF) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, errno, NULL, 1.44 +1 -1 apache-2.0/src/modules/mpm/mpmt_pthread/mpmt_pthread.c Index: mpmt_pthread.c =================================================================== RCS file: /home/cvs/apache-2.0/src/modules/mpm/mpmt_pthread/mpmt_pthread.c,v retrieving revision 1.43 retrieving revision 1.44 diff -u -r1.43 -r1.44 --- mpmt_pthread.c 1999/11/11 22:57:19 1.43 +++ mpmt_pthread.c 1999/11/15 19:50:11 1.44 @@ -737,7 +737,7 @@ sock_disable_nagle(csd); - iol = unix_attach_socket(csd); + iol = unix_attach_socket(sock); if (iol == NULL) { if (errno == EBADF) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL, 1.51 +1 -1 apache-2.0/src/modules/mpm/prefork/prefork.c Index: prefork.c =================================================================== RCS file: /home/cvs/apache-2.0/src/modules/mpm/prefork/prefork.c,v retrieving revision 1.50 retrieving revision 1.51 diff -u -r1.50 -r1.51 --- prefork.c 1999/11/09 09:33:52 1.50 +++ prefork.c 1999/11/15 19:50:25 1.51 @@ -2218,7 +2218,7 @@ sock_disable_nagle(sockdes); - iol = unix_attach_socket(sockdes); + iol = unix_attach_socket(csd); if (iol == NULL) { if (errno == EBADF) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, NULL, 1.11 +31 -131 apache-2.0/src/os/unix/iol_socket.c Index: iol_socket.c =================================================================== RCS file: /home/cvs/apache-2.0/src/os/unix/iol_socket.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- iol_socket.c 1999/10/30 00:25:31 1.10 +++ iol_socket.c 1999/11/15 19:50:31 1.11 @@ -58,19 +58,15 @@ #include "httpd.h" #include "ap_iol.h" +#include "apr_network_io.h" +#include "apr_file_io.h" #include "iol_socket.h" -#include <errno.h> -#include <sys/types.h> -#include <sys/uio.h> - #define FD_NONBLOCKING_SET (1) typedef struct { ap_iol iol; - int fd; - int flags; - int timeout; + ap_socket_t *sock; } iol_socket; static ap_status_t unix_setopt(ap_iol *viol, ap_iol_option opt, @@ -80,10 +76,10 @@ switch (opt) { case AP_IOL_TIMEOUT: - iol->timeout = *(const int *)value; - break; + ap_setsocketopt(iol->sock, APR_SO_TIMEOUT, *(const int*)value); + break; default: - return APR_EINVAL; + return APR_EINVAL; } return APR_SUCCESS; } @@ -94,138 +90,48 @@ switch (opt) { case AP_IOL_TIMEOUT: - *(int *)value = iol->timeout; - break; + /* no-op */ + break; default: - return APR_EINVAL; + return APR_EINVAL; } return APR_SUCCESS; } -static ap_status_t set_nonblock(int fd) -{ - int fd_flags; - int rv; - fd_flags = fcntl(fd, F_GETFL, 0); -#if defined(O_NONBLOCK) - fd_flags |= O_NONBLOCK; - rv = fcntl(fd, F_SETFL, fd_flags); -#elif defined(O_NDELAY) - fd_flags |= O_NDELAY; - rv = fcntl(fd, F_SETFL, fd_flags); -#elif defined(FNDELAY) - fd_flags |= O_FNDELAY; - rv = fcntl(fd, F_SETFL, fd_flags); -#else -#error "your unix lacks non-blocking i/o, you lose" -#endif - if (rv == 0) { - return APR_SUCCESS; - } - return errno; +ap_status_t unix_write(ap_iol *viol, const char* buf, ap_size_t size, + ap_ssize_t *nbytes) +{ + *nbytes = size; + return ap_send(((iol_socket *)viol)->sock, buf, nbytes); } -/* the timeout code is a separate routine because it requires - a stack frame... and we don't want to pay that setup cost - on every call */ - -/* this macro expands into the four basic i/o methods */ - -#define method(name, args, syscall, selread, selwrite) \ - static ap_status_t unix_##name##_timeout args \ - { \ - iol_socket *iol = (iol_socket *)viol; \ - fd_set fdset; \ - struct timeval tv; \ - int rv; \ - \ - FD_ZERO(&fdset); \ - FD_SET(iol->fd, &fdset); \ - tv.tv_sec = iol->timeout; \ - tv.tv_usec = 0; \ - do { \ - rv = select(iol->fd + 1, selread, selwrite, NULL, iol->timeout < 0 ? NULL : &tv); \ - } while (rv == -1 && errno == EINTR); \ - if (!FD_ISSET(iol->fd, &fdset)) { \ - *nbytes = 0; \ - return APR_ETIMEDOUT; \ - } \ - do { \ - rv = syscall(iol->fd, arg1, arg2); \ - } while (rv == -1 && errno == EINTR); \ - if (rv >= 0) { \ - *nbytes = rv; \ - return APR_SUCCESS; \ - } \ - *nbytes = 0; \ - return errno; \ - \ - } \ - \ - static ap_status_t unix_##name args \ - { \ - iol_socket *iol = (iol_socket *)viol; \ - int rv; \ - \ - /* Preset to zero until some bytes are actually written */ \ - *nbytes = 0; \ - if (!(iol->flags & FD_NONBLOCKING_SET)) { \ - if (iol->timeout < 0) { \ - rv = syscall(iol->fd, arg1, arg2); \ - if (rv >= 0) { \ - *nbytes = rv; \ - return APR_SUCCESS; \ - } \ - return errno; \ - } \ - /* must shift descriptor to blocking mode now */ \ - if ((rv = set_nonblock(iol->fd)) != APR_SUCCESS) { \ - return rv; \ - } \ - iol->flags |= FD_NONBLOCKING_SET; \ - } \ - \ - /* try writing, ignoring EINTR, the upper layer has to handle \ - partial read/writes anyhow, so we can return early */ \ - do { \ - rv = syscall(iol->fd, arg1, arg2); \ - } while (rv == -1 && errno == EINTR); \ - if (rv >= 0) { \ - *nbytes = rv; \ - return APR_SUCCESS; \ - } \ - if ((errno == EWOULDBLOCK || errno == EAGAIN) && iol->timeout != 0) { \ - return unix_##name##_timeout(viol, arg1, arg2, nbytes); \ - } \ - return errno; \ - } +ap_status_t unix_writev(ap_iol *viol, const struct iovec *vec, int nvec, + ap_ssize_t *nbytes) +{ + *nbytes = vec[0].iov_len; + return ap_send(((iol_socket *)viol)->sock, vec[0].iov_base, nbytes); +} -method(write, (ap_iol *viol, const char *arg1, ap_size_t arg2, ap_ssize_t *nbytes), write, NULL, &fdset) -method(writev, (ap_iol *viol, const struct iovec *arg1, int arg2, ap_ssize_t *nbytes), writev, NULL, &fdset) -method(read, (ap_iol *viol, char *arg1, ap_size_t arg2, ap_ssize_t *nbytes), read, &fdset, NULL) +ap_status_t unix_read(ap_iol *viol, char* buf, ap_size_t size, + ap_ssize_t *nbytes) +{ + *nbytes = size; + return ap_recv(((iol_socket *)viol)->sock, buf, nbytes); +} static ap_status_t unix_close(ap_iol *viol) { - -/* XXX: This is a *temporary* ultra-hack solution to the double-close problem. - * APR and buff were both trying to close this socket */ - - return APR_SUCCESS; - -#if 0 iol_socket *iol = (iol_socket *)viol; - int rv; int saved_errno; - rv = close(iol->fd); - saved_errno = errno; + saved_errno = ap_close_socket(iol->sock); free(iol); - if (rv == 0) { + iol = NULL; + if (saved_errno == 0) { return APR_SUCCESS; } return saved_errno; -#endif } static const ap_iol_methods socket_methods = { @@ -237,18 +143,12 @@ unix_getopt }; -ap_iol *unix_attach_socket(int fd) +ap_iol *unix_attach_socket(ap_socket_t *sock) { iol_socket *iol; - if (fd >= FD_SETSIZE) { - errno = EBADF; - return NULL; - } iol = malloc(sizeof(iol_socket)); iol->iol.methods = &socket_methods; - iol->fd = fd; - iol->timeout = -1; - iol->flags = 0; + iol->sock = sock; return (ap_iol *)iol; } 1.2 +1 -1 apache-2.0/src/os/unix/iol_socket.h Index: iol_socket.h =================================================================== RCS file: /home/cvs/apache-2.0/src/os/unix/iol_socket.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- iol_socket.h 1999/06/24 08:58:04 1.1 +++ iol_socket.h 1999/11/15 19:50:31 1.2 @@ -58,6 +58,6 @@ #ifndef OS_UNIX_IOL_SOCKET_H #define OS_UNIX_IOL_SOCKET_H -ap_iol *unix_attach_socket(int fd); +ap_iol *unix_attach_socket(ap_socket_t *sock); #endif