Browse Source

Merge branch 'workqueue_squashed'

Nick Mathewson 10 years ago
parent
commit
3b6d2f9bf4

+ 1 - 2
Makefile.am

@@ -140,8 +140,7 @@ check-spaces:
 		$(top_srcdir)/src/common/*.[ch] \
 		$(top_srcdir)/src/or/*.[ch] \
 		$(top_srcdir)/src/test/*.[ch] \
-		$(top_srcdir)/src/tools/*.[ch] \
-		$(top_srcdir)/src/tools/tor-fw-helper/*.[ch]
+		$(top_srcdir)/src/tools/*.[ch]
 
 check-docs: all
 	$(PERL) $(top_builddir)/scripts/maint/checkOptionDocs.pl

+ 6 - 0
changes/workqueue_reply_t

@@ -0,0 +1,6 @@
+  o Minor bugfixes:
+    - Ensure that worker threads actually exit when a fatal error or
+      shutdown is indicated. This doesn't currently affect the behaviour
+      of Tor, because Tor never indicates fatal error or shutdown except
+      in its unit tests. Fixes bug 16868; bugfix on 0.2.6.3-alpha.
+

+ 1 - 5
doc/include.am

@@ -13,7 +13,7 @@
 # just use the .1 and .html files.
 
 base_mans = doc/tor doc/tor-gencert doc/tor-resolve doc/torify
-all_mans = $(base_mans) doc/tor-fw-helper
+all_mans = $(base_mans)
 if USE_FW_HELPER
 install_mans = $(all_mans)
 else
@@ -57,13 +57,11 @@ doc/tor.1.in: doc/tor.1.txt
 doc/torify.1.in: doc/torify.1.txt
 doc/tor-gencert.1.in: doc/tor-gencert.1.txt
 doc/tor-resolve.1.in: doc/tor-resolve.1.txt
-doc/tor-fw-helper.1.in: doc/tor-fw-helper.1.txt
 
 doc/tor.html.in: doc/tor.1.txt
 doc/torify.html.in: doc/torify.1.txt
 doc/tor-gencert.html.in: doc/tor-gencert.1.txt
 doc/tor-resolve.html.in: doc/tor-resolve.1.txt
-doc/tor-fw-helper.html.in: doc/tor-fw-helper.1.txt
 
 # use config.status to swap all machine-specific magic strings
 # in the asciidoc with their replacements.
@@ -78,13 +76,11 @@ doc/tor.html: doc/tor.html.in
 doc/tor-gencert.html: doc/tor-gencert.html.in
 doc/tor-resolve.html: doc/tor-resolve.html.in
 doc/torify.html: doc/torify.html.in
-doc/tor-fw-helper.html: doc/tor-fw-helper.html.in
 
 doc/tor.1: doc/tor.1.in
 doc/tor-gencert.1: doc/tor-gencert.1.in
 doc/tor-resolve.1: doc/tor-resolve.1.in
 doc/torify.1: doc/torify.1.in
-doc/tor-fw-helper.1: doc/tor-fw-helper.1.in
 
 CLEANFILES+= $(asciidoc_product) config.log
 DISTCLEANFILES+= $(html_in) $(man_in)

+ 0 - 60
doc/tor-fw-helper.1.txt

@@ -1,60 +0,0 @@
-// Copyright (c) The Tor Project, Inc.
-// See LICENSE for licensing information
-// This is an asciidoc file used to generate the manpage/html reference.
-// Learn asciidoc on http://www.methods.co.nz/asciidoc/userguide.html
-:man source:   Tor
-:man manual:   Tor Manual
-tor-fw-helper(1)
-================
-Jacob Appelbaum
-
-NAME
-----
-tor-fw-helper - Manage upstream firewall/NAT devices
-
-SYNOPSIS
---------
-**tor-fw-helper** [-h|--help] [-T|--test-commandline] [-v|--verbose] [-g|--fetch-public-ip]
- [-p __external port__:__internal_port__]
-
-DESCRIPTION
------------
-**tor-fw-helper** currently supports Apple's NAT-PMP protocol and the UPnP
-standard for TCP port mapping. It is written as the reference implementation of
-tor-fw-helper-spec.txt and conforms to that loose plugin API.  If your network
-supports either NAT-PMP or UPnP, tor-fw-helper will attempt to automatically
-map the required TCP ports for Tor's Or and Dir ports. +
-
-OPTIONS
--------
-**-h** or **--help**::
-    Display help text and exit.
-
-**-v** or **--verbose**::
-    Display verbose output.
-
-**-T** or **--test-commandline**::
-    Display test information and print the test information in
-    tor-fw-helper.log
-
-**-g** or **--fetch-public-ip**::
-    Fetch the the public ip address for each supported NAT helper method.
-
-**-p** or **--port** __external_port__:__internal_port__::
-    Forward external_port to internal_port.  This option can appear
-    more than once.
-
-BUGS
-----
-This probably doesn't run on Windows. That's not a big issue, since we don't
-really want to deal with Windows before October 2010 anyway.
-
-SEE ALSO
---------
-**tor**(1) +
-
-See also the "tor-fw-helper-spec.txt" file, distributed with Tor.
-
-AUTHORS
--------
-    Jacob Appelbaum <jacob@torproject.org>, Steven J. Murdoch <Steven.Murdoch@cl.cam.ac.uk>

+ 2 - 1
scripts/maint/checkSpace.pl

@@ -129,7 +129,8 @@ for $fn (@ARGV) {
                     $1 ne "switch" and $1 ne "return" and $1 ne "int" and
                     $1 ne "elsif" and $1 ne "WINAPI" and $2 ne "WINAPI" and
                     $1 ne "void" and $1 ne "__attribute__" and $1 ne "op" and
-                    $1 ne "size_t" and $1 ne "double") {
+                    $1 ne "size_t" and $1 ne "double" and
+                    $1 ne "workqueue_reply_t") {
                     print "     fn ():$fn:$.\n";
                 }
             }

+ 0 - 1
scripts/maint/format_changelog.py

@@ -36,7 +36,6 @@ NO_HYPHENATE=set("""
 pf-divert
 tor-resolve
 tor-gencert
-tor-fw-helper
 """.split())
 
 LASTLINE_UNDERFLOW_EXPONENT = 1

+ 1 - 0
src/common/compat.c

@@ -3424,3 +3424,4 @@ tor_get_avail_disk_space(const char *path)
   return -1;
 #endif
 }
+

+ 2 - 1
src/common/container.h

@@ -110,7 +110,8 @@ void smartlist_sort_digests256(smartlist_t *sl);
 void smartlist_sort_pointers(smartlist_t *sl);
 
 const char *smartlist_get_most_frequent_string(smartlist_t *sl);
-const char *smartlist_get_most_frequent_string_(smartlist_t *sl, int *count_out);
+const char *smartlist_get_most_frequent_string_(smartlist_t *sl,
+                                                int *count_out);
 const uint8_t *smartlist_get_most_frequent_digest256(smartlist_t *sl);
 
 void smartlist_uniq_strings(smartlist_t *sl);

+ 11 - 10
src/common/workqueue.c

@@ -25,7 +25,7 @@ struct threadpool_s {
   unsigned generation;
 
   /** Function that should be run for updates on each thread. */
-  int (*update_fn)(void *, void *);
+  workqueue_reply_t (*update_fn)(void *, void *);
   /** Function to free update arguments if they can't be run. */
   void (*free_update_arg_fn)(void *);
   /** Array of n_threads update arguments. */
@@ -56,7 +56,7 @@ struct workqueue_entry_s {
   /** True iff this entry is waiting for a worker to start processing it. */
   uint8_t pending;
   /** Function to run in the worker thread. */
-  int (*fn)(void *state, void *arg);
+  workqueue_reply_t (*fn)(void *state, void *arg);
   /** Function to run while processing the reply queue. */
   void (*reply_fn)(void *arg);
   /** Argument for the above functions. */
@@ -96,7 +96,7 @@ static void queue_reply(replyqueue_t *queue, workqueue_entry_t *work);
  * <b>fn</b> in the worker thread, and <b>reply_fn</b> in the main
  * thread. See threadpool_queue_work() for full documentation. */
 static workqueue_entry_t *
-workqueue_entry_new(int (*fn)(void*, void*),
+workqueue_entry_new(workqueue_reply_t (*fn)(void*, void*),
                     void (*reply_fn)(void*),
                     void *arg)
 {
@@ -172,7 +172,7 @@ worker_thread_main(void *thread_)
   workerthread_t *thread = thread_;
   threadpool_t *pool = thread->in_pool;
   workqueue_entry_t *work;
-  int result;
+  workqueue_reply_t result;
 
   tor_mutex_acquire(&pool->lock);
   while (1) {
@@ -182,13 +182,14 @@ worker_thread_main(void *thread_)
       if (thread->in_pool->generation != thread->generation) {
         void *arg = thread->in_pool->update_args[thread->index];
         thread->in_pool->update_args[thread->index] = NULL;
-        int (*update_fn)(void*,void*) = thread->in_pool->update_fn;
+        workqueue_reply_t (*update_fn)(void*,void*) =
+            thread->in_pool->update_fn;
         thread->generation = thread->in_pool->generation;
         tor_mutex_release(&pool->lock);
 
-        int r = update_fn(thread->state, arg);
+        workqueue_reply_t r = update_fn(thread->state, arg);
 
-        if (r < 0) {
+        if (r != WQ_RPL_REPLY) {
           return;
         }
 
@@ -208,7 +209,7 @@ worker_thread_main(void *thread_)
       queue_reply(thread->reply_queue, work);
 
       /* We may need to exit the thread. */
-      if (result >= WQ_RPL_ERROR) {
+      if (result != WQ_RPL_REPLY) {
         return;
       }
       tor_mutex_acquire(&pool->lock);
@@ -281,7 +282,7 @@ workerthread_new(void *state, threadpool_t *pool, replyqueue_t *replyqueue)
  */
 workqueue_entry_t *
 threadpool_queue_work(threadpool_t *pool,
-                      int (*fn)(void *, void *),
+                      workqueue_reply_t (*fn)(void *, void *),
                       void (*reply_fn)(void *),
                       void *arg)
 {
@@ -318,7 +319,7 @@ threadpool_queue_work(threadpool_t *pool,
 int
 threadpool_queue_update(threadpool_t *pool,
                          void *(*dup_fn)(void *),
-                         int (*fn)(void *, void *),
+                         workqueue_reply_t (*fn)(void *, void *),
                          void (*free_fn)(void *),
                          void *arg)
 {

+ 10 - 9
src/common/workqueue.h

@@ -15,21 +15,22 @@ typedef struct threadpool_s threadpool_t;
  * pool. */
 typedef struct workqueue_entry_s workqueue_entry_t;
 
-/** Possible return value from a work function: indicates success. */
-#define WQ_RPL_REPLY    0
-/** Possible return value from a work function: indicates fatal error */
-#define WQ_RPL_ERROR    1
-/** Possible return value from a work function: indicates thread is shutting
- * down. */
-#define WQ_RPL_SHUTDOWN 2
+/** Possible return value from a work function: */
+typedef enum {
+  WQ_RPL_REPLY = 0, /** indicates success */
+  WQ_RPL_ERROR = 1, /** indicates fatal error */
+  WQ_RPL_SHUTDOWN = 2, /** indicates thread is shutting down */
+} workqueue_reply_t;
 
 workqueue_entry_t *threadpool_queue_work(threadpool_t *pool,
-                                         int (*fn)(void *, void *),
+                                         workqueue_reply_t (*fn)(void *,
+                                                                 void *),
                                          void (*reply_fn)(void *),
                                          void *arg);
+
 int threadpool_queue_update(threadpool_t *pool,
                             void *(*dup_fn)(void *),
-                            int (*fn)(void *, void *),
+                            workqueue_reply_t (*fn)(void *, void *),
                             void (*free_fn)(void *),
                             void *arg);
 void *workqueue_entry_cancel(workqueue_entry_t *pending_work);

+ 1 - 0
src/or/control.c

@@ -6478,3 +6478,4 @@ control_testing_set_global_event_mask(uint64_t mask)
   global_event_mask = mask;
 }
 #endif
+

+ 2 - 2
src/or/cpuworker.c

@@ -160,7 +160,7 @@ typedef struct cpuworker_job_u {
   } u;
 } cpuworker_job_t;
 
-static int
+static workqueue_reply_t
 update_state_threadfn(void *state_, void *work_)
 {
   worker_state_t *state = state_;
@@ -387,7 +387,7 @@ cpuworker_onion_handshake_replyfn(void *work_)
 }
 
 /** Implementation function for onion handshake requests. */
-static int
+static workqueue_reply_t
 cpuworker_onion_handshake_threadfn(void *state_, void *work_)
 {
   worker_state_t *state = state_;

+ 1 - 1
src/or/rendcache.c

@@ -330,7 +330,7 @@ cache_failure_intro_lookup(const uint8_t *identity, const char *service_id,
     *intro_entry = intro_elem;
   }
   return 1;
-not_found:
+ not_found:
   return 0;
 }
 

+ 5 - 4
src/or/rendclient.c

@@ -1021,7 +1021,7 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
         /* fall through */
       case INTRO_POINT_FAILURE_GENERIC:
         rend_cache_intro_failure_note(failure_type,
-                                      (uint8_t *) failed_intro->identity_digest,
+                                      (uint8_t *)failed_intro->identity_digest,
                                       rend_query->onion_address);
         rend_intro_point_free(intro);
         smartlist_del(ent->parsed->intro_nodes, i);
@@ -1038,9 +1038,10 @@ rend_client_report_intro_point_failure(extend_info_t *failed_intro,
                    intro->unreachable_count,
                    zap_intro_point ? " Removing from descriptor.": "");
           if (zap_intro_point) {
-            rend_cache_intro_failure_note(failure_type,
-                                          (uint8_t *) failed_intro->identity_digest,
-                                          rend_query->onion_address);
+            rend_cache_intro_failure_note(
+                failure_type,
+                (uint8_t *) failed_intro->identity_digest,
+                rend_query->onion_address);
             rend_intro_point_free(intro);
             smartlist_del(ent->parsed->intro_nodes, i);
           }

+ 0 - 1
src/test/test_util.c

@@ -3654,7 +3654,6 @@ test_util_di_map(void *arg)
   dimap_free(dimap, tor_free_);
 }
 
-
 /**
  * Test counting high bits
  */

+ 26 - 3
src/test/test_workqueue.c

@@ -70,7 +70,7 @@ mark_handled(int serial)
 #endif
 }
 
-static int
+static workqueue_reply_t
 workqueue_do_rsa(void *state, void *work)
 {
   rsa_work_t *rw = work;
@@ -98,7 +98,7 @@ workqueue_do_rsa(void *state, void *work)
   return WQ_RPL_REPLY;
 }
 
-static int
+static workqueue_reply_t
 workqueue_do_shutdown(void *state, void *work)
 {
   (void)state;
@@ -108,7 +108,7 @@ workqueue_do_shutdown(void *state, void *work)
   return WQ_RPL_SHUTDOWN;
 }
 
-static int
+static workqueue_reply_t
 workqueue_do_ecdh(void *state, void *work)
 {
   ecdh_work_t *ew = work;
@@ -124,6 +124,14 @@ workqueue_do_ecdh(void *state, void *work)
   return WQ_RPL_REPLY;
 }
 
+static workqueue_reply_t
+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,9 @@ 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 +436,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;