summaryrefslogtreecommitdiff
path: root/src/network_writev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/network_writev.c')
-rw-r--r--src/network_writev.c45
1 files changed, 20 insertions, 25 deletions
diff --git a/src/network_writev.c b/src/network_writev.c
index 96a2a4a..5fdec8c 100644
--- a/src/network_writev.c
+++ b/src/network_writev.c
@@ -26,27 +26,6 @@
#include "log.h"
#include "stat_cache.h"
-#ifndef UIO_MAXIOV
-# if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
-/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
-# define UIO_MAXIOV 1024
-# elif defined(__sgi)
-/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
-# define UIO_MAXIOV 512
-# elif defined(__sun)
-/* Solaris (and SunOS?) defines IOV_MAX instead */
-# ifndef IOV_MAX
-# define UIO_MAXIOV 16
-# else
-# define UIO_MAXIOV IOV_MAX
-# endif
-# elif defined(IOV_MAX)
-# define UIO_MAXIOV IOV_MAX
-# else
-# error UIO_MAXIOV nor IOV_MAX are defined
-# endif
-#endif
-
#if 0
#define LOCAL_BUFFERING 1
#endif
@@ -65,18 +44,31 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
ssize_t r;
size_t num_chunks, i;
- struct iovec chunks[UIO_MAXIOV];
+ struct iovec *chunks;
chunk *tc;
size_t num_bytes = 0;
-
+#if defined(_SC_IOV_MAX) /* IRIX, MacOS X, FreeBSD, Solaris, ... */
+ const size_t max_chunks = sysconf(_SC_IOV_MAX);
+#elif defined(IOV_MAX) /* Linux x86 (glibc-2.3.6-3) */
+ const size_t max_chunks = IOV_MAX;
+#elif defined(MAX_IOVEC) /* Linux ia64 (glibc-2.3.3-98.28) */
+ const size_t max_chunks = MAX_IOVEC;
+#elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */
+ const size_t max_chunks = UIO_MAXIOV;
+#else
+#error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to jan@kneschke.de"
+#endif
+
/* we can't send more then SSIZE_MAX bytes in one chunk */
/* build writev list
*
- * 1. limit: num_chunks < UIO_MAXIOV
+ * 1. limit: num_chunks < max_chunks
* 2. limit: num_bytes < SSIZE_MAX
*/
- for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
+ for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < max_chunks; num_chunks++, tc = tc->next);
+
+ chunks = calloc(num_chunks, sizeof(*chunks));
for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
if (tc->mem->used == 0) {
@@ -111,11 +103,13 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
break;
case EPIPE:
case ECONNRESET:
+ free(chunks);
return -2;
default:
log_error_write(srv, __FILE__, __LINE__, "ssd",
"writev failed:", strerror(errno), fd);
+ free(chunks);
return -1;
}
}
@@ -147,6 +141,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq
break;
}
}
+ free(chunks);
break;
}