Implemented file descriptor inheritance for NT.

Modified files: _winnt.h, prfile.c, prio.c, prsocket.c, ntio.c,
w32poll.c, and prinit.c.
This commit is contained in:
wtc%netscape.com 1999-02-05 06:45:06 +00:00
parent 953bb13843
commit 4932b6b8fc
7 changed files with 314 additions and 204 deletions

View File

@ -176,10 +176,9 @@ struct _MDFileDesc {
* for this osfd has been committed and
* cannot be changed. The osfd has been
* either associated with the io
* completion port or made nonblocking.
* This is only used for sockets, not
* for files. */
PRBool nonoverlapped;
* completion port or made nonblocking. */
PRBool sync_file_io; /* Use synchronous file I/O on the osfd
* (a file handle) */
PRBool accepted_socket; /* Is this an accepted socket (on the
* server side)? */
PRNetAddr peer_addr; /* If this is an accepted socket, cache
@ -241,6 +240,8 @@ extern PRInt32 _PR_MD_CLOSE(PRInt32 osfd, PRBool socket);
#define _MD_GETSOCKOPT _PR_MD_GETSOCKOPT
#define _MD_SETSOCKOPT _PR_MD_SETSOCKOPT
#define _MD_SELECT select
extern int _PR_NTFiberSafeSelect(int, fd_set *, fd_set *, fd_set *,
const struct timeval *);
#define _MD_FSYNC _PR_MD_FSYNC
#define _MD_SOCKETAVAILABLE _PR_MD_SOCKETAVAILABLE
#define _MD_SET_FD_INHERITABLE _PR_MD_SET_FD_INHERITABLE

View File

@ -548,8 +548,8 @@ PR_IMPLEMENT(PRStatus) PR_CreatePipe(
return PR_FAILURE;
}
#ifdef WINNT
(*readPipe)->secret->md.nonoverlapped = PR_TRUE;
(*writePipe)->secret->md.nonoverlapped = PR_TRUE;
(*readPipe)->secret->md.sync_file_io = PR_TRUE;
(*writePipe)->secret->md.sync_file_io = PR_TRUE;
#endif
return PR_SUCCESS;
#elif defined(XP_UNIX)

View File

@ -41,9 +41,9 @@ void _PR_InitIO(void)
_pr_stderr = PR_AllocFileDesc((PRInt32)GetStdHandle(STD_ERROR_HANDLE),
methods);
#ifdef WINNT
_pr_stdin->secret->md.nonoverlapped = PR_TRUE;
_pr_stdout->secret->md.nonoverlapped = PR_TRUE;
_pr_stderr->secret->md.nonoverlapped = PR_TRUE;
_pr_stdin->secret->md.sync_file_io = PR_TRUE;
_pr_stdout->secret->md.sync_file_io = PR_TRUE;
_pr_stderr->secret->md.sync_file_io = PR_TRUE;
#endif
#else
_pr_stdin = PR_AllocFileDesc(0, methods);

View File

@ -349,8 +349,15 @@ PRIntervalTime timeout)
}
fd2->secret->nonblocking = fd->secret->nonblocking;
fd2->secret->inheritable = fd->secret->inheritable;
#ifdef WINNT
fd2->secret->md.io_model_committed = PR_TRUE;
if (!fd2->secret->nonblocking && !fd2->secret->inheritable) {
/*
* The new socket has been associated with an I/O
* completion port. There is no going back.
*/
fd2->secret->md.io_model_committed = PR_TRUE;
}
PR_ASSERT(al == PR_NETADDR_SIZE(addr));
fd2->secret->md.accepted_socket = PR_TRUE;
memcpy(&fd2->secret->md.peer_addr, addr, al);

View File

@ -1069,17 +1069,25 @@ _PR_MD_FAST_ACCEPT(PRFileDesc *fd, PRNetAddr *raddr, PRUint32 *rlen,
PRUint32 llen, err;
int rv;
if (!_nt_use_async || fd->secret->nonblocking) {
if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) {
if (!fd->secret->md.io_model_committed) {
rv = _md_MakeNonblock((HANDLE)osfd);
PR_ASSERT(0 != rv);
fd->secret->md.io_model_committed = PR_TRUE;
}
/*
* The accepted socket inherits the nonblocking attribute of
* the listening socket, so no need to call _md_MakeNonblock().
* The accepted socket inherits the nonblocking and
* inheritable (HANDLE_FLAG_INHERIT) attributes of
* the listening socket.
*/
return _nt_nonblock_accept(fd, (struct sockaddr_in *)raddr, rlen, timeout);
accept_sock = _nt_nonblock_accept(fd, (struct sockaddr_in *)raddr, rlen, timeout);
if (_nt_use_async && !fd->secret->nonblocking) {
u_long zero = 0;
rv = ioctlsocket(accept_sock, FIONBIO, &zero);
PR_ASSERT(0 == rv);
}
return accept_sock;
}
if (me->io_suspended) {
@ -1436,7 +1444,7 @@ _PR_MD_RECV(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
int bytes;
int rv, err;
if (!_nt_use_async || fd->secret->nonblocking) {
if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) {
if (!fd->secret->md.io_model_committed) {
rv = _md_MakeNonblock((HANDLE)osfd);
PR_ASSERT(0 != rv);
@ -1513,7 +1521,7 @@ _PR_MD_SEND(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
int bytes;
int rv, err;
if (!_nt_use_async || fd->secret->nonblocking) {
if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) {
if (!fd->secret->md.io_model_committed) {
rv = _md_MakeNonblock((HANDLE)osfd);
PR_ASSERT(0 != rv);
@ -1589,7 +1597,7 @@ _PR_MD_SENDTO(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags,
PR_ASSERT(0 != rv);
fd->secret->md.io_model_committed = PR_TRUE;
}
if (_nt_use_async && !fd->secret->nonblocking)
if (_nt_use_async && !fd->secret->nonblocking && !fd->secret->inheritable)
return pt_SendTo(osfd, buf, amount, flags, addr, addrlen, timeout);
else
return _nt_nonblock_sendto(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout);
@ -1607,7 +1615,7 @@ _PR_MD_RECVFROM(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags,
PR_ASSERT(0 != rv);
fd->secret->md.io_model_committed = PR_TRUE;
}
if (_nt_use_async && !fd->secret->nonblocking)
if (_nt_use_async && !fd->secret->nonblocking && !fd->secret->inheritable)
return pt_RecvFrom(osfd, buf, amount, flags, addr, addrlen, timeout);
else
return _nt_nonblock_recvfrom(fd, buf, amount, (struct sockaddr *)addr, addrlen, timeout);
@ -1622,7 +1630,7 @@ _PR_MD_WRITEV(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTi
int sent = 0;
int rv;
if (!_nt_use_async || fd->secret->nonblocking) {
if (!_nt_use_async || fd->secret->nonblocking || fd->secret->inheritable) {
if (!fd->secret->md.io_model_committed) {
rv = _md_MakeNonblock((HANDLE)osfd);
PR_ASSERT(0 != rv);
@ -1792,12 +1800,7 @@ _PR_MD_OPEN(const char *name, PRIntn osflags, PRIntn mode)
flag6,
NULL);
if (file == INVALID_HANDLE_VALUE) {
_PR_MD_MAP_OPEN_ERROR(GetLastError());
return -1;
}
if (_md_Associate(file) == 0) {
CloseHandle(file);
_PR_MD_MAP_OPEN_ERROR(GetLastError());
return -1;
}
@ -1854,7 +1857,7 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
PRUint32 bytes;
int rv, err;
if (_nt_use_async && !fd->secret->md.nonoverlapped) {
if (_nt_use_async && !fd->secret->md.sync_file_io) {
PRThread *me = _PR_MD_CURRENT_THREAD();
if (me->io_suspended) {
@ -1866,52 +1869,88 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
me->io_pending = PR_TRUE;
me->io_fd = f;
me->state = _PR_IO_WAIT;
rv = ReadFile((HANDLE)f,
(LPVOID)buf,
len,
&bytes,
&me->md.overlapped.overlapped);
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
if (err == ERROR_HANDLE_EOF)
return 0;
_PR_MD_MAP_READ_ERROR(err);
return -1;
}
if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
PR_ASSERT(0);
return -1;
}
PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
if (me->io_suspended) {
if (_PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
} else {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
if (fd->secret->inheritable) {
rv = ReadFile((HANDLE)f,
(LPVOID)buf,
len,
&bytes,
&me->md.overlapped.overlapped);
if (rv != 0) {
SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT);
return bytes;
}
return -1;
}
if (me->md.blocked_io_status == 0) {
if (me->md.blocked_io_error == ERROR_HANDLE_EOF)
err = GetLastError();
if (err == ERROR_IO_PENDING) {
rv = GetOverlappedResult((HANDLE)f,
&me->md.overlapped.overlapped, &bytes, TRUE);
if (rv != 0) {
SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT);
return bytes;
}
err = GetLastError();
}
if (err == ERROR_HANDLE_EOF) {
return 0;
_PR_MD_MAP_READ_ERROR(me->md.blocked_io_error);
return -1;
}
} else {
_PR_MD_MAP_READ_ERROR(err);
return -1;
}
} else {
if (!fd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)f);
PR_ASSERT(rv != 0);
fd->secret->md.io_model_committed = PR_TRUE;
}
SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT);
me->io_pending = PR_TRUE;
me->io_fd = f;
me->state = _PR_IO_WAIT;
rv = ReadFile((HANDLE)f,
(LPVOID)buf,
len,
&bytes,
&me->md.overlapped.overlapped);
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
if (err == ERROR_HANDLE_EOF) {
return 0;
}
_PR_MD_MAP_READ_ERROR(err);
return -1;
}
if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
PR_ASSERT(0);
return -1;
}
PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
if (me->io_suspended) {
if (_PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
} else {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
}
return -1;
}
if (me->md.blocked_io_status == 0) {
if (me->md.blocked_io_error == ERROR_HANDLE_EOF) {
return 0;
}
_PR_MD_MAP_READ_ERROR(me->md.blocked_io_error);
return -1;
}
SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT);
PR_ASSERT(me->io_pending == PR_FALSE);
PR_ASSERT(me->io_pending == PR_FALSE);
return me->md.blocked_io_bytes;
return me->md.blocked_io_bytes;
}
} else {
rv = ReadFile((HANDLE)f,
@ -1927,7 +1966,7 @@ _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
/* The write end of the pipe has been closed. */
return 0;
}
_PR_MD_MAP_READ_ERROR(err);
_PR_MD_MAP_READ_ERROR(err);
return -1;
}
return bytes;
@ -1941,7 +1980,7 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len)
PRInt32 bytes;
int rv, err;
if (_nt_use_async && !fd->secret->md.nonoverlapped) {
if (_nt_use_async && !fd->secret->md.sync_file_io) {
PRThread *me = _PR_MD_CURRENT_THREAD();
if (me->io_suspended) {
@ -1953,48 +1992,78 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len)
me->md.overlapped.overlapped.Offset = SetFilePointer((HANDLE)f, 0, 0, FILE_CURRENT);
me->io_pending = PR_TRUE;
me->io_fd = f;
me->state = _PR_IO_WAIT;
rv = WriteFile((HANDLE)f,
buf,
len,
&bytes,
&(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
_PR_MD_MAP_WRITE_ERROR(err);
return -1;
}
if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
PR_ASSERT(0);
return -1;
}
PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
if (me->io_suspended) {
if (_PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
} else {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
if (fd->secret->inheritable) {
rv = WriteFile((HANDLE)f,
(LPVOID)buf,
len,
&bytes,
&me->md.overlapped.overlapped);
if (rv != 0) {
SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT);
return bytes;
}
err = GetLastError();
if (err == ERROR_IO_PENDING) {
rv = GetOverlappedResult((HANDLE)f,
&me->md.overlapped.overlapped, &bytes, TRUE);
if (rv != 0) {
SetFilePointer((HANDLE)f, bytes, 0, FILE_CURRENT);
return bytes;
}
err = GetLastError();
}
_PR_MD_MAP_READ_ERROR(err);
return -1;
}
} else {
if (!fd->secret->md.io_model_committed) {
rv = _md_Associate((HANDLE)f);
PR_ASSERT(rv != 0);
fd->secret->md.io_model_committed = PR_TRUE;
}
if (me->md.blocked_io_status == 0) {
_PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error);
return -1;
}
me->io_pending = PR_TRUE;
me->io_fd = f;
me->state = _PR_IO_WAIT;
rv = WriteFile((HANDLE)f,
buf,
len,
&bytes,
&(me->md.overlapped.overlapped));
if ( (rv == 0) && ((err = GetLastError()) != ERROR_IO_PENDING) ) {
me->io_pending = PR_FALSE;
me->state = _PR_RUNNING;
_PR_MD_MAP_WRITE_ERROR(err);
return -1;
}
SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT);
if (_NT_IO_WAIT(me, PR_INTERVAL_NO_TIMEOUT) == PR_FAILURE) {
PR_ASSERT(0);
return -1;
}
PR_ASSERT(me->io_pending == PR_FALSE || me->io_suspended == PR_TRUE);
if (me->io_suspended) {
if (_PR_PENDING_INTERRUPT(me)) {
me->flags &= ~_PR_INTERRUPT;
PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
} else {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
}
return -1;
}
if (me->md.blocked_io_status == 0) {
_PR_MD_MAP_WRITE_ERROR(me->md.blocked_io_error);
return -1;
}
SetFilePointer((HANDLE)f, me->md.blocked_io_bytes, 0, FILE_CURRENT);
PR_ASSERT(me->io_pending == PR_FALSE);
PR_ASSERT(me->io_pending == PR_FALSE);
return me->md.blocked_io_bytes;
return me->md.blocked_io_bytes;
}
} else {
rv = WriteFile((HANDLE)f,
buf,
@ -2002,7 +2071,7 @@ _PR_MD_WRITE(PRFileDesc *fd, void *buf, PRInt32 len)
&bytes,
NULL);
if (rv == 0) {
_PR_MD_MAP_WRITE_ERROR(GetLastError());
_PR_MD_MAP_WRITE_ERROR(GetLastError());
return -1;
}
return bytes;
@ -2187,6 +2256,10 @@ _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable)
{
BOOL rv;
if (fd->secret->md.io_model_committed) {
PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
return PR_FAILURE;
}
rv = SetHandleInformation(
(HANDLE)fd->secret->md.osfd,
HANDLE_FLAG_INHERIT,
@ -3121,48 +3194,49 @@ PRInt32 _nt_nonblock_accept(PRFileDesc *fd, struct sockaddr_in *addr, int *len,
while ((rv = accept(osfd, (struct sockaddr *) addr, len)) == -1) {
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking)) {
if ((rv = select(osfd + 1, &rd, NULL, NULL,NULL)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
NULL)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
}
}
} else {
_PR_MD_MAP_ACCEPT_ERROR(err);
_PR_MD_MAP_ACCEPT_ERROR(err);
break;
}
}
}
return(rv);
} else if (timeout == PR_INTERVAL_NO_WAIT) {
if ((rv = accept(osfd, (struct sockaddr *) addr, len)) == -1)
if ((rv = accept(osfd, (struct sockaddr *) addr, len)) == -1) {
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking)) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
} else {
_PR_MD_MAP_ACCEPT_ERROR(err);
}
return(rv);
} else {
retry:
if ((rv = accept(osfd, (struct sockaddr *) addr, len)) == -1) {
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking)) {
tv.tv_sec = PR_IntervalToSeconds(timeout);
tv.tv_usec = PR_IntervalToMicroseconds(
timeout - PR_SecondsToInterval(tv.tv_sec));
tvp = &tv;
rv = select(osfd + 1, &rd, NULL, NULL, tvp);
if (rv > 0) {
goto retry;
} else if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
rv = -1;
} else
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
} else {
_PR_MD_MAP_ACCEPT_ERROR(err);
}
_PR_MD_MAP_ACCEPT_ERROR(err);
}
}
} else {
retry:
if ((rv = accept(osfd, (struct sockaddr *) addr, len)) == -1) {
if (((err = WSAGetLastError()) == WSAEWOULDBLOCK)
&& (!fd->secret->nonblocking)) {
tv.tv_sec = PR_IntervalToSeconds(timeout);
tv.tv_usec = PR_IntervalToMicroseconds(
timeout - PR_SecondsToInterval(tv.tv_sec));
tvp = &tv;
rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL, tvp);
if (rv > 0) {
goto retry;
} else if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
rv = -1;
} else {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
}
} else {
_PR_MD_MAP_ACCEPT_ERROR(err);
}
}
}
return(rv);
}
@ -3186,16 +3260,17 @@ PRInt32 _nt_nonblock_recv(PRFileDesc *fd, char *buf, int len, PRIntervalTime tim
timeout - PR_SecondsToInterval(tv.tv_sec));
tvp = &tv;
}
if ((rv = select(osfd + 1, &rd, NULL,NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
} else if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
rv = -1;
break;
}
} else {
_PR_MD_MAP_RECV_ERROR(err);
_PR_MD_MAP_RECV_ERROR(err);
break;
}
}
@ -3224,24 +3299,25 @@ PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime tim
}
FD_ZERO(&wd);
FD_SET((SOCKET)osfd, &wd);
if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
}
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
}
if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
return -1;
}
} else {
_PR_MD_MAP_SEND_ERROR(err);
_PR_MD_MAP_SEND_ERROR(err);
return -1;
}
}
}
bytesSent += rv;
if (fd->secret->nonblocking) {
break;
}
if ((rv >= 0) && (bytesSent < len)) {
if (bytesSent < len) {
if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
tvp = NULL;
} else {
@ -3252,12 +3328,13 @@ PRInt32 _nt_nonblock_send(PRFileDesc *fd, char *buf, int len, PRIntervalTime tim
}
FD_ZERO(&wd);
FD_SET((SOCKET)osfd, &wd);
if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
}
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
}
if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
return -1;
}
}
@ -3276,7 +3353,7 @@ PRInt32 _nt_nonblock_writev(PRFileDesc *fd, const PRIOVec *iov, int size, PRInte
if (rv > 0)
sent += rv;
if ( rv != iov[index].iov_len ) {
if (rv <= 0) {
if (rv < 0) {
if (fd->secret->nonblocking
&& (PR_GetError() == PR_WOULD_BLOCK_ERROR)
&& (sent > 0)) {
@ -3318,24 +3395,25 @@ PRInt32 _nt_nonblock_sendto(
}
FD_ZERO(&wd);
FD_SET((SOCKET)osfd, &wd);
if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
}
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
}
if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
return -1;
}
} else {
_PR_MD_MAP_SENDTO_ERROR(err);
_PR_MD_MAP_SENDTO_ERROR(err);
return -1;
}
}
}
bytesSent += rv;
if (fd->secret->nonblocking) {
break;
}
if ((rv >= 0) && (bytesSent < len)) {
if (bytesSent < len) {
if ( timeout == PR_INTERVAL_NO_TIMEOUT ) {
tvp = NULL;
} else {
@ -3346,12 +3424,13 @@ PRInt32 _nt_nonblock_sendto(
}
FD_ZERO(&wd);
FD_SET((SOCKET)osfd, &wd);
if ((rv = select(osfd + 1, NULL, &wd, NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
}
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, NULL, &wd, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
}
if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
return -1;
}
}
@ -3379,16 +3458,17 @@ PRInt32 _nt_nonblock_recvfrom(PRFileDesc *fd, char *buf, int len, struct sockadd
}
FD_ZERO(&rd);
FD_SET((SOCKET)osfd, &rd);
if ((rv = select(osfd + 1, &rd, NULL,NULL,tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
return -1;
if ((rv = _PR_NTFiberSafeSelect(osfd + 1, &rd, NULL, NULL,
tvp)) == -1) {
_PR_MD_MAP_SELECT_ERROR(WSAGetLastError());
break;
} else if (rv == 0) {
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
PR_SetError(PR_IO_TIMEOUT_ERROR, 0);
rv = -1;
break;
}
} else {
_PR_MD_MAP_RECVFROM_ERROR(err);
_PR_MD_MAP_RECVFROM_ERROR(err);
break;
}
}

View File

@ -28,7 +28,7 @@ struct select_data_s {
PRInt32 status;
PRInt32 error;
fd_set *rd, *wt, *ex;
struct timeval *tv;
const struct timeval *tv;
};
static void
@ -43,6 +43,46 @@ _PR_MD_select_thread(void *cdata)
}
}
int _PR_NTFiberSafeSelect(
int nfds,
fd_set *readfds,
fd_set *writefds,
fd_set *exceptfds,
const struct timeval *timeout)
{
PRThread *me = _PR_MD_CURRENT_THREAD();
int ready;
if (_PR_IS_NATIVE_THREAD(me)) {
ready = _MD_SELECT(nfds, readfds, writefds, exceptfds, timeout);
}
else
{
/*
** Creating a new thread on each call!!
** I guess web server doesn't use non-block I/O.
*/
PRThread *selectThread;
struct select_data_s data;
data.status = 0;
data.error = 0;
data.rd = readfds;
data.wt = writefds;
data.ex = exceptfds;
data.tv = timeout;
selectThread = PR_CreateThread(
PR_USER_THREAD, _PR_MD_select_thread, &data,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
if (selectThread == NULL) return -1;
PR_JoinThread(selectThread);
ready = data.status;
if (ready == SOCKET_ERROR) WSASetLastError(data.error);
}
return ready;
}
#endif /* !defined(_PR_GLOBAL_THREADS_ONLY) */
PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
@ -183,33 +223,7 @@ PRInt32 _PR_MD_PR_POLL(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
#if defined(_PR_GLOBAL_THREADS_ONLY)
ready = _MD_SELECT(0, &rd, &wt, &ex, tvp);
#else
if (_PR_IS_NATIVE_THREAD(me)) {
ready = _MD_SELECT(0, &rd, &wt, &ex, tvp);
}
else
{
/*
** Creating a new thread on each call to Poll()!!
** I guess web server doesn't use non-block I/O.
*/
PRThread *selectThread;
struct select_data_s data;
data.status = 0;
data.error = 0;
data.rd = &rd;
data.wt = &wt;
data.ex = &ex;
data.tv = tvp;
selectThread = PR_CreateThread(
PR_USER_THREAD, _PR_MD_select_thread, &data,
PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
if (selectThread == NULL) return -1;
PR_JoinThread(selectThread);
ready = data.status;
if (ready == SOCKET_ERROR) WSASetLastError(data.error);
}
ready = _PR_NTFiberSafeSelect(0, &rd, &wt, &ex, tvp);
#endif
/*

View File

@ -482,7 +482,7 @@ PR_ProcessAttrSetInheritableFD(
#define OSFD_STRLEN 10
/* The length of fd type (PRDescType) printed in decimal */
#define FD_TYPE_STRLEN 1
int newSize;
PRSize newSize;
int remainder;
char *newBuffer;
int nwritten;
@ -581,6 +581,14 @@ PR_IMPLEMENT(PRFileDesc *) PR_GetInheritedFD(
fd = NULL;
break;
}
if (fd) {
/*
* An inherited FD is inheritable by default.
* The child process needs to call PR_SetFDInheritable
* to make it non-inheritable if so desired.
*/
fd->secret->inheritable = PR_TRUE;
}
return fd;
}
/* Skip three colons */