Bugzilla bug 132208: added the 'tcp_nodelay' field to Linux's _MDFileDesc,
which is set by pt_SetSocketOption or pt_Accept and used by pt_LinuxSendFile to avoid a setsockopt(TCP_CORK) call that is bound to fail. Modified files: _unixos.h ptio.c git-svn-id: svn://10.0.0.236/trunk@117649 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -145,6 +145,9 @@ extern PRUint32 _pr_md_ioq_timeout;
|
||||
|
||||
struct _MDFileDesc {
|
||||
int osfd;
|
||||
#if defined(LINUX) && defined(_PR_PTHREADS)
|
||||
int tcp_nodelay; /* used by pt_LinuxSendFile */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _MDDir {
|
||||
|
||||
@@ -1661,6 +1661,14 @@ static PRFileDesc* pt_Accept(
|
||||
{
|
||||
PR_ASSERT(IsValidNetAddr(addr) == PR_TRUE);
|
||||
PR_ASSERT(IsValidNetAddrLen(addr, addr_len) == PR_TRUE);
|
||||
#ifdef LINUX
|
||||
/*
|
||||
* On Linux, experiments showed that the accepted sockets
|
||||
* inherit the TCP_NODELAY socket option of the listening
|
||||
* socket.
|
||||
*/
|
||||
newfd->secret->md.tcp_nodelay = fd->secret->md.tcp_nodelay;
|
||||
#endif
|
||||
}
|
||||
return newfd;
|
||||
|
||||
@@ -2512,14 +2520,28 @@ static PRInt32 pt_LinuxSendFile(PRFileDesc *sd, PRSendFileData *sfd,
|
||||
file_nbytes_to_send = sfd->file_nbytes;
|
||||
}
|
||||
|
||||
if (sfd->hlen != 0 || sfd->tlen != 0) {
|
||||
if ((sfd->hlen != 0 || sfd->tlen != 0)
|
||||
&& sd->secret->md.tcp_nodelay == 0) {
|
||||
tcp_cork = 1;
|
||||
if (setsockopt(sd->secret->md.osfd, SOL_TCP, TCP_CORK,
|
||||
&tcp_cork, sizeof tcp_cork) == -1) {
|
||||
_PR_MD_MAP_SETSOCKOPT_ERROR(errno);
|
||||
return -1;
|
||||
&tcp_cork, sizeof tcp_cork) == 0) {
|
||||
tcp_cork_enabled = PR_TRUE;
|
||||
} else {
|
||||
syserrno = errno;
|
||||
if (syserrno != EINVAL) {
|
||||
_PR_MD_MAP_SETSOCKOPT_ERROR(syserrno);
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* The most likely reason for the EINVAL error is that
|
||||
* TCP_NODELAY is set (with a function other than
|
||||
* PR_SetSocketOption). This is not fatal, so we keep
|
||||
* on going.
|
||||
*/
|
||||
PR_LOG(_pr_io_lm, PR_LOG_WARNING,
|
||||
("pt_LinuxSendFile: "
|
||||
"setsockopt(TCP_CORK) failed with EINVAL\n"));
|
||||
}
|
||||
tcp_cork_enabled = PR_TRUE;
|
||||
}
|
||||
|
||||
if (sfd->hlen != 0) {
|
||||
@@ -2899,6 +2921,12 @@ static PRStatus pt_SetSocketOption(PRFileDesc *fd, const PRSocketOptionData *dat
|
||||
rv = setsockopt(
|
||||
fd->secret->md.osfd, level, name,
|
||||
(char*)&value, sizeof(PRIntn));
|
||||
#ifdef LINUX
|
||||
/* for pt_LinuxSendFile */
|
||||
if (name == TCP_NODELAY && rv == 0) {
|
||||
fd->secret->md.tcp_nodelay = value;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case PR_SockOpt_McastLoopback:
|
||||
|
||||
Reference in New Issue
Block a user