rbb 2002/08/02 11:12:04
Modified: . acconfig.h configure.in
poll/unix poll.c
Log:
Remove the memory leak from the apr_poll implementation. On all systems,
this will support any number of files/sockets. On modern systems, this
will allocate on the stack. On older systems we fall back to malloc/free.
Note: We will rarely ever use malloc/free.
Revision Changes Path
1.57 +2 -0 apr/acconfig.h
Index: acconfig.h
===================================================================
RCS file: /home/cvs/apr/acconfig.h,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -r1.56 -r1.57
--- acconfig.h 20 Jul 2002 08:37:26 -0000 1.56
+++ acconfig.h 2 Aug 2002 18:12:03 -0000 1.57
@@ -48,6 +48,8 @@
#undef HAVE_INT64_C
+#undef HAVE_VLA
+
/* BeOS specific flag */
#undef HAVE_BONE_VERSION
1.469 +11 -1 apr/configure.in
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.468
retrieving revision 1.469
diff -u -r1.468 -r1.469
--- configure.in 24 Jul 2002 20:29:37 -0000 1.468
+++ configure.in 2 Aug 2002 18:12:03 -0000 1.469
@@ -793,7 +793,7 @@
dnl #----------------------------- Checks for Any required Functions
dnl Checks for library functions. (N.B. poll is further down)
-AC_CHECK_FUNCS(calloc strcasecmp stricmp setsid isinf isnan)
+AC_CHECK_FUNCS(alloca calloc strcasecmp stricmp setsid isinf isnan)
AC_CHECK_FUNCS(setrlimit, [ have_setrlimit="1" ], [ have_setrlimit="0" ])
AC_CHECK_FUNCS(getrlimit, [ have_getrlimit="1" ], [ have_getrlimit="0" ])
AC_CHECK_FUNCS(writev)
@@ -1280,6 +1280,16 @@
[ oc=1 ] )
AC_SUBST(oc)
+
+AC_MSG_CHECKING(for Variable Length Arrays)
+APR_TRY_COMPILE_NO_WARNING([],
+[
+ int foo[atoi(argv[1])];
+], vla_msg=yes, vla_msg=no )
+AC_MSG_RESULT([$vla_msg])
+if test "$vla_msg" = "yes"; then
+ AC_DEFINE(HAVE_VLA)
+fi
AC_CACHE_CHECK(struct rlimit,ac_cv_struct_rlimit,[
AC_TRY_RUN([
1.17 +16 -9 apr/poll/unix/poll.c
Index: poll.c
===================================================================
RCS file: /home/cvs/apr/poll/unix/poll.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- poll.c 2 Aug 2002 05:42:23 -0000 1.16
+++ poll.c 2 Aug 2002 18:12:04 -0000 1.17
@@ -111,24 +111,25 @@
APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num,
apr_int32_t *nsds, apr_interval_time_t timeout)
{
+ int i;
+#ifdef HAVE_VLA
+ struct pollfd pollset[num];
+#elif defined(HAVE_ALLOCA)
+ struct pollfd *pollset = alloca(sizeof(pollfd) * num);
+#else
struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT];
struct pollfd *pollset;
- int i;
if (num <= SMALL_POLLSET_LIMIT) {
pollset = tmp_pollset;
}
else {
- /* XXX There are two problems with this code: it leaks
- * memory, and it requires an O(n)-time loop to copy
- * n descriptors from the apr_pollfd_t structs into
- * the pollfd structs. At the moment, it's best suited
- * for use with fewer than SMALL_POLLSET_LIMIT
- * descriptors.
+ /* This does require O(n) to copy the descriptors to the internal
+ * mapping.
*/
- pollset = apr_palloc(aprset->p,
- sizeof(struct pollfd) * num);
+ pollset = malloc(sizeof(struct pollfd) * num);
}
+#endif
for (i = 0; i < num; i++) {
if (aprset[i].desc_type == APR_POLL_SOCKET) {
pollset[i].fd = aprset[i].desc.s->socketdes;
@@ -150,6 +151,12 @@
aprset[i].rtnevents = get_revent(pollset[i].revents);
}
+#if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA)
+ if (num > SMALL_POLLSET_LIMIT) {
+ free(pollset);
+ }
+#endif
+
if ((*nsds) < 0) {
return errno;
}