📄 unix.c
字号:
rv = fsync(fd->secret->md.osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_FSYNC_ERROR(err); } return(rv);}PRInt32 _MD_close(PRInt32 osfd){PRInt32 rv, err; rv = close(osfd); if (rv == -1) { err = _MD_ERRNO(); _PR_MD_MAP_CLOSE_ERROR(err); } return(rv);}PRInt32 _MD_socket(PRInt32 domain, PRInt32 type, PRInt32 proto){ PRInt32 osfd, err; osfd = socket(domain, type, proto); if (osfd == -1) { err = _MD_ERRNO(); _PR_MD_MAP_SOCKET_ERROR(err); return(osfd); } return(osfd);}PRInt32 _MD_socketavailable(PRFileDesc *fd){ PRInt32 result; if (ioctl(fd->secret->md.osfd, FIONREAD, &result) < 0) { _PR_MD_MAP_SOCKETAVAILABLE_ERROR(_MD_ERRNO()); return -1; } return result;}PRInt64 _MD_socketavailable64(PRFileDesc *fd){ PRInt64 result; LL_I2L(result, _MD_socketavailable(fd)); return result;} /* _MD_socketavailable64 */#define READ_FD 1#define WRITE_FD 2/* * socket_io_wait -- * * wait for socket i/o, periodically checking for interrupt * * The first implementation uses select(), for platforms without * poll(). The second (preferred) implementation uses poll(). */#ifndef _PR_USE_POLLstatic PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout){ PRInt32 rv = -1; struct timeval tv; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; fd_set rd_wr; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; FD_ZERO(&rd_wr); do { FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; FD_ZERO(&rd_wr); do { /* * We block in _MD_SELECT for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; tv.tv_sec = PR_IntervalToSeconds(remaining); if (tv.tv_sec > _PR_INTERRUPT_CHECK_INTERVAL_SECS) { wait_for_remaining = PR_FALSE; tv.tv_sec = _PR_INTERRUPT_CHECK_INTERVAL_SECS; tv.tv_usec = 0; } else { tv.tv_usec = PR_IntervalToMicroseconds( remaining - PR_SecondsToInterval(tv.tv_sec)); } FD_SET(osfd, &rd_wr); if (fd_type == READ_FD) rv = _MD_SELECT(osfd + 1, &rd_wr, NULL, NULL, &tv); else rv = _MD_SELECT(osfd + 1, NULL, &rd_wr, NULL, &tv); /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_SELECT_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * We loop again if _MD_SELECT timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If _MD_SELECT timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { now += PR_SecondsToInterval(tv.tv_sec) + PR_MicrosecondsToInterval(tv.tv_usec); } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv);}#else /* _PR_USE_POLL */static PRInt32 socket_io_wait(PRInt32 osfd, PRInt32 fd_type, PRIntervalTime timeout){ PRInt32 rv = -1; int msecs; PRThread *me = _PR_MD_CURRENT_THREAD(); PRIntervalTime epoch, now, elapsed, remaining; PRBool wait_for_remaining; PRInt32 syserror; struct pollfd pfd; switch (timeout) { case PR_INTERVAL_NO_WAIT: PR_SetError(PR_IO_TIMEOUT_ERROR, 0); break; case PR_INTERVAL_NO_TIMEOUT: /* * This is a special case of the 'default' case below. * Please see the comments there. */ msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; pfd.fd = osfd; if (fd_type == READ_FD) { pfd.events = POLLIN; } else { pfd.events = POLLOUT; } do { rv = _MD_POLL(&pfd, 1, msecs); if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_POLL_ERROR(syserror); break; } /* * If POLLERR is set, don't process it; retry the operation */ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { rv = -1; _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; default: now = epoch = PR_IntervalNow(); remaining = timeout; pfd.fd = osfd; if (fd_type == READ_FD) { pfd.events = POLLIN; } else { pfd.events = POLLOUT; } do { /* * We block in _MD_POLL for at most * _PR_INTERRUPT_CHECK_INTERVAL_SECS seconds, * so that there is an upper limit on the delay * before the interrupt bit is checked. */ wait_for_remaining = PR_TRUE; msecs = PR_IntervalToMilliseconds(remaining); if (msecs > _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000) { wait_for_remaining = PR_FALSE; msecs = _PR_INTERRUPT_CHECK_INTERVAL_SECS * 1000; } rv = _MD_POLL(&pfd, 1, msecs); /* * we don't consider EINTR a real error */ if (rv == -1 && (syserror = _MD_ERRNO()) != EINTR) { _PR_MD_MAP_POLL_ERROR(syserror); break; } if (_PR_PENDING_INTERRUPT(me)) { me->flags &= ~_PR_INTERRUPT; PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0); rv = -1; break; } /* * If POLLERR is set, don't process it; retry the operation */ if ((rv == 1) && (pfd.revents & (POLLHUP | POLLNVAL))) { rv = -1; _PR_MD_MAP_POLL_REVENTS_ERROR(pfd.revents); break; } /* * We loop again if _MD_POLL timed out or got interrupted * by a signal, and the timeout deadline has not passed yet. */ if (rv == 0 || (rv == -1 && syserror == EINTR)) { /* * If _MD_POLL timed out, we know how much time * we spent in blocking, so we can avoid a * PR_IntervalNow() call. */ if (rv == 0) { if (wait_for_remaining) { now += remaining; } else { now += PR_MillisecondsToInterval(msecs); } } else { now = PR_IntervalNow(); } elapsed = (PRIntervalTime) (now - epoch); if (elapsed >= timeout) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; break; } else { remaining = timeout - elapsed; } } } while (rv == 0 || (rv == -1 && syserror == EINTR)); break; } return(rv);}#endif /* _PR_USE_POLL */static PRInt32 local_io_wait( PRInt32 osfd, PRInt32 wait_flag, PRIntervalTime timeout){ _PRUnixPollDesc pd; PRInt32 rv; PR_LOG(_pr_io_lm, PR_LOG_MIN, ("waiting to %s on osfd=%d", (wait_flag == _PR_UNIX_POLL_READ) ? "read" : "write", osfd)); if (timeout == PR_INTERVAL_NO_WAIT) return 0; pd.osfd = osfd; pd.in_flags = wait_flag; pd.out_flags = 0; rv = _PR_WaitForMultipleFDs(&pd, 1, timeout); if (rv == 0) { PR_SetError(PR_IO_TIMEOUT_ERROR, 0); rv = -1; } return rv;}PRInt32 _MD_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout){ PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD();/* * Many OS's (Solaris, Unixware) have a broken recv which won't read * from socketpairs. As long as we don't use flags on socketpairs, this * is a decent fix. - mikep */#if defined(UNIXWARE) || defined(SOLARIS) || defined(NCR) while ((rv = read(osfd,buf,amount)) == -1) {#else while ((rv = recv(osfd,buf,amount,flags)) == -1) {#endif err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd,_PR_UNIX_POLL_READ,timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECV_ERROR(err); }done: return(rv);}PRInt32 _MD_recvfrom(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRNetAddr *addr, PRUint32 *addrlen, PRIntervalTime timeout){ PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD(); while ((*addrlen = PR_NETADDR_SIZE(addr)), ((rv = recvfrom(osfd, buf, amount, flags, (struct sockaddr *) addr, (_PRSockLen_t *)addrlen)) == -1)) { err = _MD_ERRNO(); if ((err == EAGAIN) || (err == EWOULDBLOCK)) { if (fd->secret->nonblocking) { break; } if (!_PR_IS_NATIVE_THREAD(me)) { if ((rv = local_io_wait(osfd, _PR_UNIX_POLL_READ, timeout)) < 0) goto done; } else { if ((rv = socket_io_wait(osfd, READ_FD, timeout)) < 0) goto done; } } else if ((err == EINTR) && (!_PR_PENDING_INTERRUPT(me))){ continue; } else { break; } } if (rv < 0) { _PR_MD_MAP_RECVFROM_ERROR(err); }done:#ifdef _PR_HAVE_SOCKADDR_LEN if (rv != -1) { /* ignore the sa_len field of struct sockaddr */ if (addr) { addr->raw.family = ((struct sockaddr *) addr)->sa_family; } }#endif /* _PR_HAVE_SOCKADDR_LEN */ return(rv);}PRInt32 _MD_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRInt32 flags, PRIntervalTime timeout){ PRInt32 osfd = fd->secret->md.osfd; PRInt32 rv, err; PRThread *me = _PR_MD_CURRENT_THREAD();#if defined(SOLARIS) PRInt32 tmp_amount = amount;#endif /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -