From 866bc07188d689fa5a64f0b43caef28dafa8bf8f Mon Sep 17 00:00:00 2001 From: "wtc%netscape.com" Date: Wed, 27 Mar 2002 15:13:49 +0000 Subject: [PATCH] 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 --- mozilla/nsprpub/pr/include/md/_unixos.h | 3 ++ mozilla/nsprpub/pr/src/pthreads/ptio.c | 38 +++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/mozilla/nsprpub/pr/include/md/_unixos.h b/mozilla/nsprpub/pr/include/md/_unixos.h index 345c48d5ee3..25ae239ca6f 100644 --- a/mozilla/nsprpub/pr/include/md/_unixos.h +++ b/mozilla/nsprpub/pr/include/md/_unixos.h @@ -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 { diff --git a/mozilla/nsprpub/pr/src/pthreads/ptio.c b/mozilla/nsprpub/pr/src/pthreads/ptio.c index da1b5df93cf..435622a653a 100644 --- a/mozilla/nsprpub/pr/src/pthreads/ptio.c +++ b/mozilla/nsprpub/pr/src/pthreads/ptio.c @@ -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: