|  | @@ -124,6 +124,14 @@ workqueue_do_ecdh(void *state, void *work)
 | 
	
		
			
				|  |  |    return WQ_RPL_REPLY;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +static int
 | 
	
		
			
				|  |  | +workqueue_shutdown_error(void *state, void *work)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  (void)state;
 | 
	
		
			
				|  |  | +  (void)work;
 | 
	
		
			
				|  |  | +  return WQ_RPL_REPLY;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static void *
 | 
	
		
			
				|  |  |  new_state(void *arg)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -156,6 +164,7 @@ static int n_sent = 0;
 | 
	
		
			
				|  |  |  static int rsa_sent = 0;
 | 
	
		
			
				|  |  |  static int ecdh_sent = 0;
 | 
	
		
			
				|  |  |  static int n_received = 0;
 | 
	
		
			
				|  |  | +static int no_shutdown = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef TRACK_RESPONSES
 | 
	
		
			
				|  |  |  bitarray_t *received;
 | 
	
	
		
			
				|  | @@ -174,6 +183,14 @@ handle_reply(void *arg)
 | 
	
		
			
				|  |  |    ++n_received;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/* This should never get called. */
 | 
	
		
			
				|  |  | +static void
 | 
	
		
			
				|  |  | +handle_reply_shutdown(void *arg)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +  (void)arg;
 | 
	
		
			
				|  |  | +  no_shutdown = 1;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  static workqueue_entry_t *
 | 
	
		
			
				|  |  |  add_work(threadpool_t *tp)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -288,6 +305,8 @@ replysock_readable_cb(tor_socket_t sock, short what, void *arg)
 | 
	
		
			
				|  |  |      shutting_down = 1;
 | 
	
		
			
				|  |  |      threadpool_queue_update(tp, NULL,
 | 
	
		
			
				|  |  |                               workqueue_do_shutdown, NULL, NULL);
 | 
	
		
			
				|  |  | +    // Anything we add after starting the shutdown must not be executed.
 | 
	
		
			
				|  |  | +    threadpool_queue_work(tp, workqueue_shutdown_error, handle_reply_shutdown, NULL);
 | 
	
		
			
				|  |  |      {
 | 
	
		
			
				|  |  |        struct timeval limit = { 2, 0 };
 | 
	
		
			
				|  |  |        tor_event_base_loopexit(tor_libevent_get_base(), &limit);
 | 
	
	
		
			
				|  | @@ -416,6 +435,9 @@ main(int argc, char **argv)
 | 
	
		
			
				|  |  |      printf("%d+%d vs %d\n", n_received, n_successful_cancel, n_sent);
 | 
	
		
			
				|  |  |      puts("FAIL");
 | 
	
		
			
				|  |  |      return 1;
 | 
	
		
			
				|  |  | +  } else if (no_shutdown) {
 | 
	
		
			
				|  |  | +    puts("Accepted work after shutdown\n");
 | 
	
		
			
				|  |  | +    puts("FAIL");
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      puts("OK");
 | 
	
		
			
				|  |  |      return 0;
 |