1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

research st: refine io.

This commit is contained in:
winlin 2014-11-06 13:11:34 +08:00
parent f8f18fffa7
commit fd0c85b324

View file

@ -54,9 +54,9 @@
#if EAGAIN != EWOULDBLOCK #if EAGAIN != EWOULDBLOCK
#define _IO_NOT_READY_ERROR ((errno == EAGAIN) || (errno == EWOULDBLOCK)) #define _IO_NOT_READY_ERROR ((errno == EAGAIN) || (errno == EWOULDBLOCK))
#else #else
#define _IO_NOT_READY_ERROR (errno == EAGAIN) #define _IO_NOT_READY_ERROR (errno == EAGAIN)
#endif #endif
#define _LOCAL_MAXIOV 16 #define _LOCAL_MAXIOV 16
@ -78,20 +78,23 @@ int _st_io_init(void)
sigact.sa_handler = SIG_IGN; sigact.sa_handler = SIG_IGN;
sigemptyset(&sigact.sa_mask); sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0; sigact.sa_flags = 0;
if (sigaction(SIGPIPE, &sigact, NULL) < 0) if (sigaction(SIGPIPE, &sigact, NULL) < 0) {
return -1; return -1;
}
/* Set maximum number of open file descriptors */ /* Set maximum number of open file descriptors */
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
return -1; return -1;
}
fdlim = (*_st_eventsys->fd_getlimit)(); fdlim = (*_st_eventsys->fd_getlimit)();
if (fdlim > 0 && rlim.rlim_max > (rlim_t) fdlim) { if (fdlim > 0 && rlim.rlim_max > (rlim_t) fdlim) {
rlim.rlim_max = fdlim; rlim.rlim_max = fdlim;
} }
rlim.rlim_cur = rlim.rlim_max; rlim.rlim_cur = rlim.rlim_max;
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
return -1; return -1;
}
_st_osfd_limit = (int) rlim.rlim_max; _st_osfd_limit = (int) rlim.rlim_max;
return 0; return 0;
@ -106,14 +109,17 @@ int st_getfdlimit(void)
void st_netfd_free(_st_netfd_t *fd) void st_netfd_free(_st_netfd_t *fd)
{ {
if (!fd->inuse) if (!fd->inuse) {
return; return;
}
fd->inuse = 0; fd->inuse = 0;
if (fd->aux_data) if (fd->aux_data) {
_st_netfd_free_aux_data(fd); _st_netfd_free_aux_data(fd);
if (fd->private_data && fd->destructor) }
if (fd->private_data && fd->destructor) {
(*(fd->destructor))(fd->private_data); (*(fd->destructor))(fd->private_data);
}
fd->private_data = NULL; fd->private_data = NULL;
fd->destructor = NULL; fd->destructor = NULL;
fd->next = _st_netfd_freelist; fd->next = _st_netfd_freelist;
@ -126,17 +132,19 @@ static _st_netfd_t *_st_netfd_new(int osfd, int nonblock, int is_socket)
_st_netfd_t *fd; _st_netfd_t *fd;
int flags = 1; int flags = 1;
if ((*_st_eventsys->fd_new)(osfd) < 0) if ((*_st_eventsys->fd_new)(osfd) < 0) {
return NULL; return NULL;
}
if (_st_netfd_freelist) { if (_st_netfd_freelist) {
fd = _st_netfd_freelist; fd = _st_netfd_freelist;
_st_netfd_freelist = _st_netfd_freelist->next; _st_netfd_freelist = _st_netfd_freelist->next;
} else { } else {
fd = calloc(1, sizeof(_st_netfd_t)); fd = calloc(1, sizeof(_st_netfd_t));
if (!fd) if (!fd) {
return NULL; return NULL;
} }
}
fd->osfd = osfd; fd->osfd = osfd;
fd->inuse = 1; fd->inuse = 1;
@ -144,11 +152,11 @@ static _st_netfd_t *_st_netfd_new(int osfd, int nonblock, int is_socket)
if (nonblock) { if (nonblock) {
/* Use just one system call */ /* Use just one system call */
if (is_socket && ioctl(osfd, FIONBIO, &flags) != -1) if (is_socket && ioctl(osfd, FIONBIO, &flags) != -1) {
return fd; return fd;
}
/* Do it the Posix way */ /* Do it the Posix way */
if ((flags = fcntl(osfd, F_GETFL, 0)) < 0 || if ((flags = fcntl(osfd, F_GETFL, 0)) < 0 || fcntl(osfd, F_SETFL, flags | O_NONBLOCK) < 0) {
fcntl(osfd, F_SETFL, flags | O_NONBLOCK) < 0) {
st_netfd_free(fd); st_netfd_free(fd);
return NULL; return NULL;
} }
@ -172,8 +180,9 @@ _st_netfd_t *st_netfd_open_socket(int osfd)
int st_netfd_close(_st_netfd_t *fd) int st_netfd_close(_st_netfd_t *fd)
{ {
if ((*_st_eventsys->fd_close)(fd->osfd) < 0) if ((*_st_eventsys->fd_close)(fd->osfd) < 0) {
return -1; return -1;
}
st_netfd_free(fd); st_netfd_free(fd);
return close(fd->osfd); return close(fd->osfd);
@ -186,14 +195,14 @@ int st_netfd_fileno(_st_netfd_t *fd)
} }
void st_netfd_setspecific(_st_netfd_t *fd, void *value, void st_netfd_setspecific(_st_netfd_t *fd, void *value, _st_destructor_t destructor)
_st_destructor_t destructor)
{ {
if (value != fd->private_data) { if (value != fd->private_data) {
/* Free up previously set non-NULL data value */ /* Free up previously set non-NULL data value */
if (fd->private_data && fd->destructor) if (fd->private_data && fd->destructor) {
(*(fd->destructor))(fd->private_data); (*(fd->destructor))(fd->private_data);
} }
}
fd->private_data = value; fd->private_data = value;
fd->destructor = destructor; fd->destructor = destructor;
} }
@ -217,8 +226,9 @@ int st_netfd_poll(_st_netfd_t *fd, int how, st_utime_t timeout)
pd.events = (short) how; pd.events = (short) how;
pd.revents = 0; pd.revents = 0;
if ((n = st_poll(&pd, 1, timeout)) < 0) if ((n = st_poll(&pd, 1, timeout)) < 0) {
return -1; return -1;
}
if (n == 0) { if (n == 0) {
/* Timed out */ /* Timed out */
errno = ETIME; errno = ETIME;
@ -232,7 +242,6 @@ int st_netfd_poll(_st_netfd_t *fd, int how, st_utime_t timeout)
return 0; return 0;
} }
#ifdef MD_ALWAYS_UNSERIALIZED_ACCEPT #ifdef MD_ALWAYS_UNSERIALIZED_ACCEPT
/* No-op */ /* No-op */
int st_netfd_serialize_accept(_st_netfd_t *fd) int st_netfd_serialize_accept(_st_netfd_t *fd)
@ -247,21 +256,23 @@ static void _st_netfd_free_aux_data(_st_netfd_t *fd)
fd->aux_data = NULL; fd->aux_data = NULL;
} }
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout)
st_utime_t timeout)
{ {
int osfd, err; int osfd, err;
_st_netfd_t *newfd; _st_netfd_t *newfd;
while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) { while ((osfd = accept(fd->osfd, addr, (socklen_t *)addrlen)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return NULL; return NULL;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return NULL; return NULL;
} }
}
/* On some platforms the new socket created by accept() inherits */ /* On some platforms the new socket created by accept() inherits */
/* the nonblocking attribute of the listening socket */ /* the nonblocking attribute of the listening socket */
@ -270,7 +281,7 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
#elif defined (MD_ACCEPT_NB_NOT_INHERITED) #elif defined (MD_ACCEPT_NB_NOT_INHERITED)
newfd = _st_netfd_new(osfd, 1, 1); newfd = _st_netfd_new(osfd, 1, 1);
#else #else
#error Unknown OS #error Unknown OS
#endif #endif
if (!newfd) { if (!newfd) {
@ -298,24 +309,25 @@ int st_netfd_serialize_accept(_st_netfd_t *fd)
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if ((p = (_st_netfd_t **)calloc(2, sizeof(_st_netfd_t *))) == NULL) if ((p = (_st_netfd_t **)calloc(2, sizeof(_st_netfd_t *))) == NULL) {
return -1; return -1;
}
if (pipe(osfd) < 0) { if (pipe(osfd) < 0) {
free(p); free(p);
return -1; return -1;
} }
if ((p[0] = st_netfd_open(osfd[0])) != NULL && if ((p[0] = st_netfd_open(osfd[0])) != NULL && (p[1] = st_netfd_open(osfd[1])) != NULL && write(osfd[1], " ", 1) == 1) {
(p[1] = st_netfd_open(osfd[1])) != NULL &&
write(osfd[1], " ", 1) == 1) {
fd->aux_data = p; fd->aux_data = p;
return 0; return 0;
} }
/* Error */ /* Error */
err = errno; err = errno;
if (p[0]) if (p[0]) {
st_netfd_free(p[0]); st_netfd_free(p[0]);
if (p[1]) }
if (p[1]) {
st_netfd_free(p[1]); st_netfd_free(p[1]);
}
close(osfd[0]); close(osfd[0]);
close(osfd[1]); close(osfd[1]);
free(p); free(p);
@ -334,8 +346,7 @@ static void _st_netfd_free_aux_data(_st_netfd_t *fd)
fd->aux_data = NULL; fd->aux_data = NULL;
} }
_st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen, st_utime_t timeout)
st_utime_t timeout)
{ {
int osfd, err; int osfd, err;
_st_netfd_t *newfd; _st_netfd_t *newfd;
@ -349,8 +360,9 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
} else { } else {
/* Get the lock */ /* Get the lock */
n = st_read(p[0], &c, 1, timeout); n = st_read(p[0], &c, 1, timeout);
if (n < 0) if (n < 0) {
return NULL; return NULL;
}
ST_ASSERT(n == 1); ST_ASSERT(n == 1);
/* Got the lock */ /* Got the lock */
osfd = accept(fd->osfd, addr, (socklen_t *)addrlen); osfd = accept(fd->osfd, addr, (socklen_t *)addrlen);
@ -360,16 +372,20 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
ST_ASSERT(n == 1); ST_ASSERT(n == 1);
errno = err; errno = err;
} }
if (osfd >= 0) if (osfd >= 0) {
break; break;
if (errno == EINTR) }
if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return NULL; return NULL;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return NULL; return NULL;
} }
}
/* On some platforms the new socket created by accept() inherits */ /* On some platforms the new socket created by accept() inherits */
/* the nonblocking attribute of the listening socket */ /* the nonblocking attribute of the listening socket */
@ -378,7 +394,7 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
#elif defined (MD_ACCEPT_NB_NOT_INHERITED) #elif defined (MD_ACCEPT_NB_NOT_INHERITED)
newfd = _st_netfd_new(osfd, 1, 1); newfd = _st_netfd_new(osfd, 1, 1);
#else #else
#error Unknown OS #error Unknown OS
#endif #endif
if (!newfd) { if (!newfd) {
@ -392,8 +408,7 @@ _st_netfd_t *st_accept(_st_netfd_t *fd, struct sockaddr *addr, int *addrlen,
#endif /* MD_ALWAYS_UNSERIALIZED_ACCEPT */ #endif /* MD_ALWAYS_UNSERIALIZED_ACCEPT */
int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen, int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen, st_utime_t timeout)
st_utime_t timeout)
{ {
int n, err = 0; int n, err = 0;
@ -407,16 +422,18 @@ int st_connect(_st_netfd_t *fd, const struct sockaddr *addr, int addrlen,
* "UNIX Network Programming," Vol. 1, 2nd edition, p. 413 * "UNIX Network Programming," Vol. 1, 2nd edition, p. 413
* ("Interrupted connect"). * ("Interrupted connect").
*/ */
if (errno != EINPROGRESS && (errno != EADDRINUSE || err == 0)) if (errno != EINPROGRESS && (errno != EADDRINUSE || err == 0)) {
return -1; return -1;
}
/* Wait until the socket becomes writable */ /* Wait until the socket becomes writable */
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
return -1; return -1;
}
/* Try to find out whether the connection setup succeeded or failed */ /* Try to find out whether the connection setup succeeded or failed */
n = sizeof(int); n = sizeof(int);
if (getsockopt(fd->osfd, SOL_SOCKET, SO_ERROR, (char *)&err, if (getsockopt(fd->osfd, SOL_SOCKET, SO_ERROR, (char *)&err, (socklen_t *)&n) < 0) {
(socklen_t *)&n) < 0)
return -1; return -1;
}
if (err) { if (err) {
errno = err; errno = err;
return -1; return -1;
@ -435,21 +452,23 @@ ssize_t st_read(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout)
ssize_t n; ssize_t n;
while ((n = read(fd->osfd, buf, nbyte)) < 0) { while ((n = read(fd->osfd, buf, nbyte)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid, int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid, st_utime_t timeout)
st_utime_t timeout)
{ {
struct iovec iov, *riov; struct iovec iov, *riov;
int riov_size, rv; int riov_size, rv;
@ -464,76 +483,78 @@ int st_read_resid(_st_netfd_t *fd, void *buf, size_t *resid,
} }
ssize_t st_readv(_st_netfd_t *fd, const struct iovec *iov, int iov_size, ssize_t st_readv(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout)
st_utime_t timeout)
{ {
ssize_t n; ssize_t n;
while ((n = readv(fd->osfd, iov, iov_size)) < 0) { while ((n = readv(fd->osfd, iov, iov_size)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
int st_readv_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, int st_readv_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout)
st_utime_t timeout)
{ {
ssize_t n; ssize_t n;
while (*iov_size > 0) { while (*iov_size > 0) {
if (*iov_size == 1) if (*iov_size == 1) {
n = read(fd->osfd, (*iov)->iov_base, (*iov)->iov_len); n = read(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
else } else {
n = readv(fd->osfd, *iov, *iov_size); n = readv(fd->osfd, *iov, *iov_size);
}
if (n < 0) { if (n < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
} else if (n == 0) }
} else if (n == 0) {
break; break;
else { } else {
while ((size_t) n >= (*iov)->iov_len) { while ((size_t) n >= (*iov)->iov_len) {
n -= (*iov)->iov_len; n -= (*iov)->iov_len;
(*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len; (*iov)->iov_base = (char *) (*iov)->iov_base + (*iov)->iov_len;
(*iov)->iov_len = 0; (*iov)->iov_len = 0;
(*iov)++; (*iov)++;
(*iov_size)--; (*iov_size)--;
if (n == 0) if (n == 0) {
break; break;
} }
if (*iov_size == 0) }
if (*iov_size == 0) {
break; break;
}
(*iov)->iov_base = (char *) (*iov)->iov_base + n; (*iov)->iov_base = (char *) (*iov)->iov_base + n;
(*iov)->iov_len -= n; (*iov)->iov_len -= n;
} }
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return -1; return -1;
} }
}
return 0; return 0;
} }
ssize_t st_read_fully(_st_netfd_t *fd, void *buf, size_t nbyte, st_utime_t timeout)
ssize_t st_read_fully(_st_netfd_t *fd, void *buf, size_t nbyte,
st_utime_t timeout)
{ {
size_t resid = nbyte; size_t resid = nbyte;
return st_read_resid(fd, buf, &resid, timeout) == 0 ? return st_read_resid(fd, buf, &resid, timeout) == 0 ? (ssize_t) (nbyte - resid) : -1;
(ssize_t) (nbyte - resid) : -1;
} }
int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid, st_utime_t timeout)
int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid,
st_utime_t timeout)
{ {
struct iovec iov, *riov; struct iovec iov, *riov;
int riov_size, rv; int riov_size, rv;
@ -547,18 +568,13 @@ int st_write_resid(_st_netfd_t *fd, const void *buf, size_t *resid,
return rv; return rv;
} }
ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte, st_utime_t timeout)
ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte,
st_utime_t timeout)
{ {
size_t resid = nbyte; size_t resid = nbyte;
return st_write_resid(fd, buf, &resid, timeout) == 0 ? return st_write_resid(fd, buf, &resid, timeout) == 0 ? (ssize_t) (nbyte - resid) : -1;
(ssize_t) (nbyte - resid) : -1;
} }
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size, st_utime_t timeout)
ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
st_utime_t timeout)
{ {
ssize_t n, rv; ssize_t n, rv;
size_t nleft, nbyte; size_t nleft, nbyte;
@ -568,8 +584,9 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
/* Calculate the total number of bytes to be sent */ /* Calculate the total number of bytes to be sent */
nbyte = 0; nbyte = 0;
for (index = 0; index < iov_size; index++) for (index = 0; index < iov_size; index++) {
nbyte += iov[index].iov_len; nbyte += iov[index].iov_len;
}
rv = (ssize_t)nbyte; rv = (ssize_t)nbyte;
nleft = nbyte; nleft = nbyte;
@ -578,25 +595,29 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
while (nleft > 0) { while (nleft > 0) {
if (iov_cnt == 1) { if (iov_cnt == 1) {
if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft) if (st_write(fd, tmp_iov[0].iov_base, nleft, timeout) != (ssize_t) nleft) {
rv = -1; rv = -1;
}
break; break;
} }
if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) { if ((n = writev(fd->osfd, tmp_iov, iov_cnt)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
}
if (!_IO_NOT_READY_ERROR) { if (!_IO_NOT_READY_ERROR) {
rv = -1; rv = -1;
break; break;
} }
} else { } else {
if ((size_t) n == nleft) if ((size_t) n == nleft) {
break; break;
}
nleft -= n; nleft -= n;
/* Find the next unwritten vector */ /* Find the next unwritten vector */
n = (ssize_t)(nbyte - nleft); n = (ssize_t)(nbyte - nleft);
for (index = 0; (size_t) n >= iov[index].iov_len; index++) for (index = 0; (size_t) n >= iov[index].iov_len; index++) {
n -= iov[index].iov_len; n -= iov[index].iov_len;
}
if (tmp_iov == iov) { if (tmp_iov == iov) {
/* Must copy iov's around */ /* Must copy iov's around */
@ -604,10 +625,11 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
tmp_iov = local_iov; tmp_iov = local_iov;
} else { } else {
tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec)); tmp_iov = calloc(1, (iov_size - index) * sizeof(struct iovec));
if (tmp_iov == NULL) if (tmp_iov == NULL) {
return -1; return -1;
} }
} }
}
/* Fill in the first partial read */ /* Fill in the first partial read */
tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]); tmp_iov[0].iov_base = &(((char *)iov[index].iov_base)[n]);
@ -626,28 +648,30 @@ ssize_t st_writev(_st_netfd_t *fd, const struct iovec *iov, int iov_size,
} }
} }
if (tmp_iov != iov && tmp_iov != local_iov) if (tmp_iov != iov && tmp_iov != local_iov) {
free(tmp_iov); free(tmp_iov);
}
return rv; return rv;
} }
int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size, st_utime_t timeout)
int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size,
st_utime_t timeout)
{ {
ssize_t n; ssize_t n;
while (*iov_size > 0) { while (*iov_size > 0) {
if (*iov_size == 1) if (*iov_size == 1) {
n = write(fd->osfd, (*iov)->iov_base, (*iov)->iov_len); n = write(fd->osfd, (*iov)->iov_base, (*iov)->iov_len);
else } else {
n = writev(fd->osfd, *iov, *iov_size); n = writev(fd->osfd, *iov, *iov_size);
}
if (n < 0) { if (n < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
} else { } else {
while ((size_t) n >= (*iov)->iov_len) { while ((size_t) n >= (*iov)->iov_len) {
n -= (*iov)->iov_len; n -= (*iov)->iov_len;
@ -655,104 +679,109 @@ int st_writev_resid(_st_netfd_t *fd, struct iovec **iov, int *iov_size,
(*iov)->iov_len = 0; (*iov)->iov_len = 0;
(*iov)++; (*iov)++;
(*iov_size)--; (*iov_size)--;
if (n == 0) if (n == 0) {
break; break;
} }
if (*iov_size == 0) }
if (*iov_size == 0) {
break; break;
}
(*iov)->iov_base = (char *) (*iov)->iov_base + n; (*iov)->iov_base = (char *) (*iov)->iov_base + n;
(*iov)->iov_len -= n; (*iov)->iov_len -= n;
} }
/* Wait until the socket becomes writable */ /* Wait until the socket becomes writable */
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
return -1; return -1;
} }
}
return 0; return 0;
} }
/* /*
* Simple I/O functions for UDP. * Simple I/O functions for UDP.
*/ */
int st_recvfrom(_st_netfd_t *fd, void *buf, int len, struct sockaddr *from, int st_recvfrom(_st_netfd_t *fd, void *buf, int len, struct sockaddr *from, int *fromlen, st_utime_t timeout)
int *fromlen, st_utime_t timeout)
{ {
int n; int n;
while ((n = recvfrom(fd->osfd, buf, len, 0, from, (socklen_t *)fromlen)) while ((n = recvfrom(fd->osfd, buf, len, 0, from, (socklen_t *)fromlen)) < 0) {
< 0) { if (errno == EINTR) {
if (errno == EINTR)
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
int st_sendto(_st_netfd_t *fd, const void *msg, int len, const struct sockaddr *to, int tolen, st_utime_t timeout)
int st_sendto(_st_netfd_t *fd, const void *msg, int len,
const struct sockaddr *to, int tolen, st_utime_t timeout)
{ {
int n; int n;
while ((n = sendto(fd->osfd, msg, len, 0, to, tolen)) < 0) { while ((n = sendto(fd->osfd, msg, len, 0, to, tolen)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes writable */ /* Wait until the socket becomes writable */
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
int st_recvmsg(_st_netfd_t *fd, struct msghdr *msg, int flags, int st_recvmsg(_st_netfd_t *fd, struct msghdr *msg, int flags, st_utime_t timeout)
st_utime_t timeout)
{ {
int n; int n;
while ((n = recvmsg(fd->osfd, msg, flags)) < 0) { while ((n = recvmsg(fd->osfd, msg, flags)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes readable */ /* Wait until the socket becomes readable */
if (st_netfd_poll(fd, POLLIN, timeout) < 0) if (st_netfd_poll(fd, POLLIN, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags, st_utime_t timeout)
int st_sendmsg(_st_netfd_t *fd, const struct msghdr *msg, int flags,
st_utime_t timeout)
{ {
int n; int n;
while ((n = sendmsg(fd->osfd, msg, flags)) < 0) { while ((n = sendmsg(fd->osfd, msg, flags)) < 0) {
if (errno == EINTR) if (errno == EINTR) {
continue; continue;
if (!_IO_NOT_READY_ERROR) }
if (!_IO_NOT_READY_ERROR) {
return -1; return -1;
}
/* Wait until the socket becomes writable */ /* Wait until the socket becomes writable */
if (st_netfd_poll(fd, POLLOUT, timeout) < 0) if (st_netfd_poll(fd, POLLOUT, timeout) < 0) {
return -1; return -1;
} }
}
return n; return n;
} }
/* /*
* To open FIFOs or other special files. * To open FIFOs or other special files.
*/ */
@ -762,9 +791,10 @@ _st_netfd_t *st_open(const char *path, int oflags, mode_t mode)
_st_netfd_t *newfd; _st_netfd_t *newfd;
while ((osfd = open(path, oflags | O_NONBLOCK, mode)) < 0) { while ((osfd = open(path, oflags | O_NONBLOCK, mode)) < 0) {
if (errno != EINTR) if (errno != EINTR) {
return NULL; return NULL;
} }
}
newfd = _st_netfd_new(osfd, 0, 0); newfd = _st_netfd_new(osfd, 0, 0);
if (!newfd) { if (!newfd) {