mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
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:
parent
953bb13843
commit
4932b6b8fc
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user