- fixed daemon destruction order to prevent
authorMartin Willi <martin@strongswan.org>
Tue, 30 May 2006 06:14:23 +0000 (06:14 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 30 May 2006 06:14:23 +0000 (06:14 -0000)
  crashes on termination

src/charon/daemon.c

index c3d7ed7..f04595e 100644 (file)
@@ -196,30 +196,36 @@ static void initialize(private_daemon_t *this)
  */
 static void destroy(private_daemon_t *this)
 {
-       if (this->public.ike_sa_manager != NULL)
-       {
-               this->public.ike_sa_manager->destroy(this->public.ike_sa_manager);
-       }
-       if (this->public.kernel_interface != NULL)
-       {
-               this->public.kernel_interface->destroy(this->public.kernel_interface);
-       }
+       /* destruction is a non trivial task, we need to follow 
+        * a strict order to prevent threading issues! 
+        * Kill active threads first, except the sender, as
+        * the killed IKE_SA want to send delete messages. 
+        */
        if (this->public.receiver != NULL)
-       {
+       {       /* we don't want to receive anything... */
                this->public.receiver->destroy(this->public.receiver);
        }
+       if (this->public.stroke != NULL)
+       {       /* ignore all incoming user requests */
+               this->public.stroke->destroy(this->public.stroke);
+       }
        if (this->public.scheduler != NULL)
-       {
+       {       /* stop scheduing jobs */
                this->public.scheduler->destroy(this->public.scheduler);        
        }
-       if (this->public.sender != NULL)
-       {
-               this->public.sender->destroy(this->public.sender);
-       }
        if (this->public.thread_pool != NULL)
-       {
+       {       /* stop processing jobs */
                this->public.thread_pool->destroy(this->public.thread_pool);    
        }
+       if (this->public.ike_sa_manager != NULL)
+       {       /* shut down manager with all IKE SAs */
+               this->public.ike_sa_manager->destroy(this->public.ike_sa_manager);
+       }
+       if (this->public.kernel_interface != NULL)
+       {       /* all child SAs should be down now, so kill kernel interface */
+               this->public.kernel_interface->destroy(this->public.kernel_interface);
+       }
+       /* destroy other infrastructure */
        if (this->public.job_queue != NULL)
        {
                this->public.job_queue->destroy(this->public.job_queue);
@@ -228,14 +234,6 @@ static void destroy(private_daemon_t *this)
        {
                this->public.event_queue->destroy(this->public.event_queue);    
        }
-       if (this->public.send_queue != NULL)
-       {
-               this->public.send_queue->destroy(this->public.send_queue);      
-       }
-       if (this->public.socket != NULL)
-       {
-               this->public.socket->destroy(this->public.socket);
-       }
        if (this->public.configuration != NULL)
        {
                this->public.configuration->destroy(this->public.configuration);
@@ -252,9 +250,19 @@ static void destroy(private_daemon_t *this)
        {
                this->public.policies->destroy(this->public.policies);
        }
-       if (this->public.stroke != NULL)
+       /* we hope the sender could send the outstanding deletes, but 
+        * we shut down here at any cost */
+       if (this->public.sender != NULL)
        {
-               this->public.stroke->destroy(this->public.stroke);
+               this->public.sender->destroy(this->public.sender);
+       }
+       if (this->public.send_queue != NULL)
+       {
+               this->public.send_queue->destroy(this->public.send_queue);      
+       }
+       if (this->public.socket != NULL)
+       {
+               this->public.socket->destroy(this->public.socket);
        }
        free(this);
 }