mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 11:55:49 +00:00
Bugsplat bug #340901: On AIX, PR_TransmitFile calls the new send_file()
system call if it is available. The patch is contributed by IBM's Anthony Moore <anthonym@npec.netscape.com>.
This commit is contained in:
parent
a75da9a89d
commit
aeaecc7b0e
@ -1525,8 +1525,15 @@ void _MD_unix_map_lockf_error(int err)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef AIX
|
||||
void _MD_aix_map_sendfile_error(int oserror)
|
||||
#endif
|
||||
|
||||
#ifdef HPUX11
|
||||
void _MD_hpux_map_sendfile_error(int oserror)
|
||||
#endif
|
||||
|
||||
#if defined(AIX) || defined(HPUX11)
|
||||
{
|
||||
PRErrorCode prerror;
|
||||
|
||||
@ -1560,4 +1567,4 @@ void _MD_hpux_map_sendfile_error(int oserror)
|
||||
}
|
||||
PR_SetError(prerror, oserror);
|
||||
}
|
||||
#endif /* HPUX11 */
|
||||
#endif /* defined(AIX) || defined(HPUX11) */
|
||||
|
@ -44,12 +44,71 @@
|
||||
#ifdef AIX
|
||||
/* To pick up sysconf() */
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h> /* for dlopen */
|
||||
#else
|
||||
/* To pick up getrlimit() etc. */
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The send_file() system call is available in AIX 4.3.2 or later.
|
||||
* If this file is compiled on an older AIX system, it attempts to
|
||||
* look up the send_file symbol at run time to determine whether
|
||||
* we can use the faster PR_TransmitFile implementation based on
|
||||
* send_file(). On AIX 4.3.2 or later, we can safely skip this
|
||||
* runtime function dispatching and just use the send_file based
|
||||
* implementation.
|
||||
*/
|
||||
#ifdef AIX
|
||||
#ifdef HAVE_SEND_FILE
|
||||
|
||||
#define AIX_SEND_FILE(a, b, c) send_file(a, b, c)
|
||||
|
||||
#else /* HAVE_SEND_FILE */
|
||||
|
||||
/*
|
||||
* The following definitions match those in <sys/socket.h>
|
||||
* on AIX 4.3.2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Structure for the send_file() system call
|
||||
*/
|
||||
struct sf_parms {
|
||||
/* --------- header parms ---------- */
|
||||
void *header_data; /* Input/Output. Points to header buf */
|
||||
uint_t header_length; /* Input/Output. Length of the header */
|
||||
/* --------- file parms ------------ */
|
||||
int file_descriptor; /* Input. File descriptor of the file */
|
||||
unsigned long long file_size; /* Output. Size of the file */
|
||||
unsigned long long file_offset; /* Input/Output. Starting offset */
|
||||
long long file_bytes; /* Input/Output. no. of bytes to send */
|
||||
/* --------- trailer parms --------- */
|
||||
void *trailer_data; /* Input/Output. Points to trailer buf */
|
||||
uint_t trailer_length; /* Input/Output. Length of the trailer */
|
||||
/* --------- return info ----------- */
|
||||
unsigned long long bytes_sent; /* Output. no. of bytes sent */
|
||||
};
|
||||
|
||||
/*
|
||||
* Flags for the send_file() system call
|
||||
*/
|
||||
#define SF_CLOSE 0x00000001 /* close the socket after completion */
|
||||
#define SF_REUSE 0x00000002 /* reuse socket. not supported */
|
||||
#define SF_DONT_CACHE 0x00000004 /* don't apply network buffer cache */
|
||||
#define SF_SYNC_CACHE 0x00000008 /* sync/update network buffer cache */
|
||||
|
||||
/*
|
||||
* prototype: size_t send_file(int *, struct sf_parms *, uint_t);
|
||||
*/
|
||||
static ssize_t (*pt_aix_sendfile_fptr)() = NULL;
|
||||
|
||||
#define AIX_SEND_FILE(a, b, c) (*pt_aix_sendfile_fptr)(a, b, c)
|
||||
|
||||
#endif /* HAVE_SEND_FILE */
|
||||
#endif /* AIX */
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
/* On Alpha Linux, these are already defined in sys/socket.h */
|
||||
@ -136,7 +195,8 @@ static PRBool IsValidNetAddrLen(const PRNetAddr *addr, PRInt32 addr_len)
|
||||
#if (defined(LINUX) && defined(__GLIBC__) && __GLIBC__ >= 2 \
|
||||
&& !defined(__alpha))
|
||||
typedef socklen_t pt_SockLen;
|
||||
#elif defined(AIX) || (defined(LINUX) && defined(__alpha))
|
||||
#elif (defined(AIX) && !defined(AIX4_1)) \
|
||||
|| (defined(LINUX) && defined(__alpha))
|
||||
typedef PRSize pt_SockLen;
|
||||
#else
|
||||
typedef PRIntn pt_SockLen;
|
||||
@ -1042,6 +1102,31 @@ static PRBool pt_recvfrom_cont(pt_Continuation *op, PRInt16 revents)
|
||||
PR_FALSE : PR_TRUE;
|
||||
} /* pt_recvfrom_cont */
|
||||
|
||||
#ifdef AIX
|
||||
static PRBool pt_aix_transmitfile_cont(pt_Continuation *op, PRInt16 revents)
|
||||
{
|
||||
struct sf_parms *sf_struct = (struct sf_parms *) op->arg2.buffer;
|
||||
int rv;
|
||||
|
||||
rv = AIX_SEND_FILE(&op->arg1.osfd, sf_struct, op->arg4.flags);
|
||||
op->syserrno = errno;
|
||||
|
||||
if (rv != -1) {
|
||||
op->result.code += sf_struct->bytes_sent;
|
||||
} else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
|
||||
op->result.code = -1;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if (rv == 1) { /* more data to send */
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
#endif /* AIX */
|
||||
|
||||
#ifdef HPUX11
|
||||
static PRBool pt_hpux_transmitfile_cont(pt_Continuation *op, PRInt16 revents)
|
||||
{
|
||||
@ -1051,10 +1136,11 @@ static PRBool pt_hpux_transmitfile_cont(pt_Continuation *op, PRInt16 revents)
|
||||
count = sendfile(op->arg1.osfd, op->filedesc, op->arg3.offset, 0,
|
||||
hdtrl, op->arg4.flags);
|
||||
PR_ASSERT(count <= op->nbytes_to_send);
|
||||
op->syserrno = errno;
|
||||
|
||||
if (count != -1) {
|
||||
op->result.code += count;
|
||||
} else if (errno != EWOULDBLOCK && errno != EAGAIN) {
|
||||
} else if (op->syserrno != EWOULDBLOCK && op->syserrno != EAGAIN) {
|
||||
op->result.code = -1;
|
||||
} else {
|
||||
return PR_FALSE;
|
||||
@ -1884,6 +1970,112 @@ static PRInt32 pt_RecvFrom(PRFileDesc *fd, void *buf, PRInt32 amount,
|
||||
return bytes;
|
||||
} /* pt_RecvFrom */
|
||||
|
||||
#ifdef AIX
|
||||
#ifndef HAVE_SEND_FILE
|
||||
static pthread_once_t pt_aix_sendfile_once_block = PTHREAD_ONCE_INIT;
|
||||
|
||||
static void pt_aix_sendfile_init_routine(void)
|
||||
{
|
||||
void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
|
||||
pt_aix_sendfile_fptr = (ssize_t (*)()) dlsym(handle, "send_file");
|
||||
dlclose(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* pt_AIXDispatchTransmitFile
|
||||
*/
|
||||
static PRInt32 pt_AIXDispatchTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
|
||||
const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = pthread_once(&pt_aix_sendfile_once_block,
|
||||
pt_aix_sendfile_init_routine);
|
||||
PR_ASSERT(0 == rv);
|
||||
if (pt_aix_sendfile_fptr) {
|
||||
return pt_AIXTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
} else {
|
||||
return _PR_UnixTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
}
|
||||
}
|
||||
#endif /* !HAVE_SEND_FILE */
|
||||
|
||||
/*
|
||||
* pt_AIXTransmitFile
|
||||
*
|
||||
* Send file fd across socket sd. If headers is non-NULL, 'hlen'
|
||||
* bytes of headers is sent before sending the file.
|
||||
*
|
||||
* PR_TRANSMITFILE_CLOSE_SOCKET flag - close socket after sending file
|
||||
*
|
||||
* return number of bytes sent or -1 on error
|
||||
*
|
||||
* This implementation takes advantage of the send_file() system
|
||||
* call available in AIX 4.3.2.
|
||||
*/
|
||||
|
||||
static PRInt32 pt_AIXTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
|
||||
const void *headers, PRInt32 hlen, PRTransmitFileFlags flags,
|
||||
PRIntervalTime timeout)
|
||||
{
|
||||
struct sf_parms sf_struct;
|
||||
uint_t send_flags;
|
||||
ssize_t rv;
|
||||
int syserrno;
|
||||
PRInt32 count;
|
||||
|
||||
sf_struct.header_data = (void *) headers; /* cast away the 'const' */
|
||||
sf_struct.header_length = hlen;
|
||||
sf_struct.file_descriptor = fd->secret->md.osfd;
|
||||
sf_struct.file_size = 0;
|
||||
sf_struct.file_offset = 0;
|
||||
sf_struct.file_bytes = -1;
|
||||
sf_struct.trailer_data = NULL;
|
||||
sf_struct.trailer_length = 0;
|
||||
sf_struct.bytes_sent = 0;
|
||||
|
||||
send_flags = 0;
|
||||
|
||||
do {
|
||||
rv = AIX_SEND_FILE(&sd->secret->md.osfd, &sf_struct, send_flags);
|
||||
} while (rv == -1 && (syserrno = errno) == EINTR);
|
||||
|
||||
if (rv == -1) {
|
||||
if (syserrno == EAGAIN || syserrno == EWOULDBLOCK) {
|
||||
count = 0; /* Not a real error. Need to continue. */
|
||||
} else {
|
||||
count = -1;
|
||||
}
|
||||
} else {
|
||||
count = sf_struct.bytes_sent;
|
||||
}
|
||||
|
||||
if ((rv == 1) || ((rv == -1) && (count == 0))) {
|
||||
pt_Continuation op;
|
||||
|
||||
op.arg1.osfd = sd->secret->md.osfd;
|
||||
op.arg2.buffer = &sf_struct;
|
||||
op.arg4.flags = send_flags;
|
||||
op.result.code = count;
|
||||
op.timeout = timeout;
|
||||
op.function = pt_aix_transmitfile_cont;
|
||||
op.event = POLLOUT | POLLPRI;
|
||||
count = pt_Continue(&op);
|
||||
syserrno = op.syserrno;
|
||||
}
|
||||
|
||||
if (count == -1) {
|
||||
_MD_aix_map_sendfile_error(syserrno);
|
||||
return -1;
|
||||
}
|
||||
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
|
||||
PR_Close(sd);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#endif /* AIX */
|
||||
|
||||
#ifdef HPUX11
|
||||
/*
|
||||
* pt_HPUXTransmitFile
|
||||
@ -1966,7 +2158,7 @@ static PRInt32 pt_HPUXTransmitFile(PRFileDesc *sd, PRFileDesc *fd,
|
||||
|
||||
if (count == -1) {
|
||||
_MD_hpux_map_sendfile_error(syserrno);
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
if (flags & PR_TRANSMITFILE_CLOSE_SOCKET) {
|
||||
PR_Close(sd);
|
||||
@ -1989,6 +2181,12 @@ static PRInt32 pt_TransmitFile(
|
||||
|
||||
#ifdef HPUX11
|
||||
return pt_HPUXTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
#elif defined(AIX)
|
||||
#ifdef HAVE_SEND_FILE
|
||||
return pt_AIXTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
#else
|
||||
return pt_AIXDispatchTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
#endif /* HAVE_SEND_FILE */
|
||||
#else
|
||||
return _PR_UnixTransmitFile(sd, fd, headers, hlen, flags, timeout);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user