You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Allan Edwards <ak...@us.ibm.com> on 2004/05/03 19:32:00 UTC

Win32 pool corruption at startup

I see startup crashes when using Win32DisableAcceptEx.
Need to prevent the child main thread and multiple worker
threads simultaneously allocating from the pchild pool.
There are also exposures in the winnt path. The
attached patch closes these holes. I'll commit shortly.

Allan


Index: child.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/mpm/winnt/child.c,v
retrieving revision 1.35
diff -u -d -b -U3 -r1.35 child.c
--- child.c	15 Mar 2004 23:08:41 -0000	1.35
+++ child.c	3 May 2004 16:59:55 -0000
@@ -58,7 +58,7 @@
  static unsigned int g_blocked_threads = 0;
  static HANDLE max_requests_per_child_event;

-
+static apr_thread_mutex_t  *child_lock;
  static apr_thread_mutex_t  *qlock;
  static PCOMP_CONTEXT qhead = NULL;
  static PCOMP_CONTEXT qtail = NULL;
@@ -145,6 +145,7 @@
                   */
                  apr_allocator_t *allocator;

+                apr_thread_mutex_lock(child_lock);
                  context = (PCOMP_CONTEXT) apr_pcalloc(pchild, sizeof(COMP_CONTEXT));

                  context->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -152,6 +153,8 @@
                      /* Hopefully this is a temporary condition ... */
                      ap_log_error(APLOG_MARK,APLOG_WARNING, apr_get_os_error(), ap_server_conf,
                                   "mpm_get_completion_context: CreateEvent failed.");
+
+                    apr_thread_mutex_unlock(child_lock);
                      return NULL;
                  }

@@ -163,6 +166,8 @@
                      ap_log_error(APLOG_MARK,APLOG_WARNING, rv, ap_server_conf,
                                   "mpm_get_completion_context: Failed to create the transaction pool.");
                      CloseHandle(context->Overlapped.hEvent);
+
+                    apr_thread_mutex_unlock(child_lock);
                      return NULL;
                  }
                  apr_allocator_owner_set(allocator, context->ptrans);
@@ -171,6 +176,8 @@
                  context->accept_socket = INVALID_SOCKET;
                  context->ba = apr_bucket_alloc_create(pchild);
                  apr_atomic_inc32(&num_completion_contexts);
+
+                apr_thread_mutex_unlock(child_lock);
                  break;
              }
          } else {
@@ -419,6 +426,7 @@
      if (context == NULL) {
          /* allocate the completion context and the transaction pool */
          apr_allocator_t *allocator;
+        apr_thread_mutex_lock(child_lock);
          context = apr_pcalloc(pchild, sizeof(COMP_CONTEXT));
          apr_allocator_create(&allocator);
          apr_allocator_max_free_set(allocator, ap_max_mem_free);
@@ -426,6 +434,7 @@
          apr_allocator_owner_set(allocator, context->ptrans);
          apr_pool_tag(context->ptrans, "transaction");
          context->ba = apr_bucket_alloc_create(pchild);
+        apr_thread_mutex_unlock(child_lock);
      }

      while (1) {
@@ -920,6 +929,8 @@
      ap_log_error(APLOG_MARK,APLOG_NOTICE, APR_SUCCESS, ap_server_conf,
                   "Child %d: Starting %d worker threads.", my_pid, ap_threads_per_child);
      child_handles = (HANDLE) apr_pcalloc(pchild, ap_threads_per_child * sizeof(int));
+    apr_thread_mutex_create(&child_lock, APR_THREAD_MUTEX_DEFAULT, pchild);
+
      while (1) {
          for (i = 0; i < ap_threads_per_child; i++) {
              int *score_idx;
@@ -943,9 +954,11 @@
              /* Save the score board index in ht keyed to the thread handle. We need this
               * when cleaning up threads down below...
               */
+            apr_thread_mutex_lock(child_lock);
              score_idx = apr_pcalloc(pchild, sizeof(int));
              *score_idx = i;
              apr_hash_set(ht, &child_handles[i], sizeof(HANDLE), score_idx);
+            apr_thread_mutex_unlock(child_lock);
          }
          /* Start the listener only when workers are available */
          if (!listener_started && threads_created) {
@@ -1128,6 +1141,8 @@

      CloseHandle(allowed_globals.jobsemaphore);
      apr_thread_mutex_destroy(allowed_globals.jobmutex);
+    apr_thread_mutex_destroy(child_lock);
+
      if (use_acceptex) {
      	apr_thread_mutex_destroy(qlock);
          CloseHandle(qwait_event);