Ver código fonte

Update transports.[ch] to support SIGHUPs.

George Kadianakis 14 anos atrás
pai
commit
1e92b24889
2 arquivos alterados com 292 adições e 73 exclusões
  1. 251 72
      src/or/transports.c
  2. 41 1
      src/or/transports.h

+ 251 - 72
src/or/transports.c

@@ -17,10 +17,7 @@
 static void set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp);
 static void set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp);
 static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
 static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
 
 
-static void managed_proxy_destroy_impl(managed_proxy_t *mp,
-                                       int also_free_transports);
-#define managed_proxy_destroy(mp) managed_proxy_destroy_impl(mp, 0)
-#define managed_proxy_destroy_with_transports(mp) managed_proxy_destroy_impl(mp, 1)
+static void managed_proxy_destroy(managed_proxy_t *mp);
 
 
 static void handle_finished_proxy(managed_proxy_t *mp);
 static void handle_finished_proxy(managed_proxy_t *mp);
 static void configure_proxy(managed_proxy_t *mp);
 static void configure_proxy(managed_proxy_t *mp);
@@ -55,14 +52,16 @@ static INLINE void free_execve_args(char **arg);
 #define PROTO_VERSION_ONE 1
 #define PROTO_VERSION_ONE 1
 
 
 /** List of unconfigured managed proxies. */
 /** List of unconfigured managed proxies. */
-static smartlist_t *unconfigured_proxy_list = NULL;
+static smartlist_t *managed_proxy_list = NULL;
+/** Number of still unconfigured proxies. */
+static int unconfigured_proxies_n = 0;
 
 
 /*  The main idea here is:
 /*  The main idea here is:
 
 
     A managed proxy is represented by a managed_proxy_t struct and can
     A managed proxy is represented by a managed_proxy_t struct and can
     spawn multiple transports.
     spawn multiple transports.
 
 
-    unconfigured_proxy_list is a list of all the unconfigured managed
+    managed_proxy_list is a list of all the unconfigured managed
     proxies; everytime we find a managed proxy in torrc we add it in
     proxies; everytime we find a managed proxy in torrc we add it in
     that list.
     that list.
     In every run_scheduled_event() tick, we attempt to launch and then
     In every run_scheduled_event() tick, we attempt to launch and then
@@ -79,8 +78,7 @@ static smartlist_t *unconfigured_proxy_list = NULL;
 int
 int
 pt_proxies_configuration_pending(void)
 pt_proxies_configuration_pending(void)
 {
 {
-  if (!unconfigured_proxy_list) return 0;
-  return !!smartlist_len(unconfigured_proxy_list);
+  return !! unconfigured_proxies_n;
 }
 }
 
 
 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
 /** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
@@ -109,10 +107,10 @@ managed_proxy_has_argv(managed_proxy_t *mp, char **proxy_argv)
 static managed_proxy_t *
 static managed_proxy_t *
 get_managed_proxy_by_argv(char **proxy_argv)
 get_managed_proxy_by_argv(char **proxy_argv)
 {
 {
-  if (!unconfigured_proxy_list)
+  if (!managed_proxy_list)
     return NULL;
     return NULL;
 
 
-  SMARTLIST_FOREACH_BEGIN(unconfigured_proxy_list,  managed_proxy_t *, mp) {
+  SMARTLIST_FOREACH_BEGIN(managed_proxy_list,  managed_proxy_t *, mp) {
     if (managed_proxy_has_argv(mp, proxy_argv))
     if (managed_proxy_has_argv(mp, proxy_argv))
       return mp;
       return mp;
   } SMARTLIST_FOREACH_END(mp);
   } SMARTLIST_FOREACH_END(mp);
@@ -129,22 +127,88 @@ add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
     smartlist_add(mp->transports_to_launch, tor_strdup(transport));
     smartlist_add(mp->transports_to_launch, tor_strdup(transport));
 }
 }
 
 
+/** Called when a SIGHUP occurs.
+ *  Returns true if managed proxy <b>mp</b> needs to be restarted
+ *  after the SIGHUP based on the new torrc. */
+static int
+proxy_needs_restart(managed_proxy_t *mp)
+{
+  /* mp->transport_to_launch is populated with the names of the
+     transports that must be launched *after* the SIGHUP.
+
+     Since only PT_PROTO_COMPLETED proxies reach this function,
+     mp->transports is populated with strings of the *names of the
+     transports* that were launched *before* the SIGHUP.
+
+     If the two lists contain the same strings, we don't need to
+     restart the proxy, since it already does what we want. */
+
+  tor_assert(smartlist_len(mp->transports_to_launch) > 0);
+  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+  if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
+    goto needs_restart;
+
+  SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
+    if (!smartlist_string_isin(mp->transports, t_t_l))
+      goto needs_restart;
+
+  } SMARTLIST_FOREACH_END(t_t_l);
+
+  return 0;
+
+ needs_restart:
+  return 1;
+}
+
+/** Managed proxy <b>mp</b> must be restarted. Do all the necessary
+ *  preparations and then flag its state so that it will be launched
+ *  in the next tick. */
+static void
+proxy_prepare_for_restart(managed_proxy_t *mp)
+{
+  transport_t *t_tmp = NULL;
+
+  tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+  tor_assert(mp->pid);
+
+  /* kill the old obfsproxy process */
+  tor_terminate_process(mp->pid);
+  mp->pid = 0;
+  fclose(mp->stdout);
+
+  /* destroy all its old transports. we no longer use them. */
+  SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
+    t_tmp = transport_get_by_name(t_name);
+    if (t_tmp)
+      t_tmp->marked_for_removal = 1;
+  } SMARTLIST_FOREACH_END(t_name);
+  sweep_transport_list();
+
+  /* free the transport names in mp->transports */
+  SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+  smartlist_clear(mp->transports);
+
+  /* flag it as an infant proxy so that it gets launched on next tick */
+  mp->conf_state = PT_PROTO_INFANT;
+}
+
 /** Launch managed proxy <b>mp</b>. */
 /** Launch managed proxy <b>mp</b>. */
 static int
 static int
 launch_managed_proxy(managed_proxy_t *mp)
 launch_managed_proxy(managed_proxy_t *mp)
 {
 {
   char **envp=NULL;
   char **envp=NULL;
-  int retval;
+  int pid;
   FILE *stdout_read = NULL;
   FILE *stdout_read = NULL;
   int stdout_pipe=-1, stderr_pipe=-1;
   int stdout_pipe=-1, stderr_pipe=-1;
 
 
   /* prepare the environment variables for the managed proxy */
   /* prepare the environment variables for the managed proxy */
   set_managed_proxy_environment(&envp, mp);
   set_managed_proxy_environment(&envp, mp);
 
 
-  retval = tor_spawn_background(mp->argv[0], &stdout_pipe,
-                                &stderr_pipe, (const char **)mp->argv,
-                                (const char **)envp);
-  if (retval < 0) {
+  pid = tor_spawn_background(mp->argv[0], &stdout_pipe,
+                             &stderr_pipe, (const char **)mp->argv,
+                             (const char **)envp);
+  if (pid < 0) {
     log_warn(LD_GENERAL, "Spawn failed");
     log_warn(LD_GENERAL, "Spawn failed");
     return -1;
     return -1;
   }
   }
@@ -157,10 +221,11 @@ launch_managed_proxy(managed_proxy_t *mp)
   /* Open the buffered IO streams */
   /* Open the buffered IO streams */
   stdout_read = fdopen(stdout_pipe, "r");
   stdout_read = fdopen(stdout_pipe, "r");
 
 
-  log_warn(LD_CONFIG, "The spawn is alive (%d)!", retval);
+  log_warn(LD_CONFIG, "The spawn is alive (%d)!", pid);
 
 
   mp->conf_state = PT_PROTO_LAUNCHED;
   mp->conf_state = PT_PROTO_LAUNCHED;
   mp->stdout = stdout_read;
   mp->stdout = stdout_read;
+  mp->pid = pid;
 
 
   return 0;
   return 0;
 }
 }
@@ -171,12 +236,32 @@ launch_managed_proxy(managed_proxy_t *mp)
 void
 void
 pt_configure_remaining_proxies(void)
 pt_configure_remaining_proxies(void)
 {
 {
-  log_warn(LD_CONFIG, "We start configuring remaining managed proxies!");
-  SMARTLIST_FOREACH_BEGIN(unconfigured_proxy_list,  managed_proxy_t *, mp) {
-    /* configured proxies shouldn't be in unconfigured_proxy_list. */
-    tor_assert(!proxy_configuration_finished(mp));
+  log_warn(LD_CONFIG, "We start configuring remaining managed proxies (%d)!",
+           unconfigured_proxies_n);
+  SMARTLIST_FOREACH_BEGIN(managed_proxy_list,  managed_proxy_t *, mp) {
+    tor_assert(mp->conf_state != PT_PROTO_BROKEN);
+
+    if (mp->got_hup) {
+      mp->got_hup = 0;
+
+    /* This proxy is marked by a SIGHUP. Check whether we need to
+       restart it. */
+      if (proxy_needs_restart(mp)) {
+        proxy_prepare_for_restart(mp);
+        continue;
+      } else { /* it doesn't need to be restarted. */
+        printf("No need for restart; status quo\n");
+        unconfigured_proxies_n--;
+        tor_assert(unconfigured_proxies_n >= 0);
+      }
+
+      continue;
+    }
 
 
-    configure_proxy(mp);
+    /* If the proxy is not fully configured, try to configure it
+       futher. */
+    if (!proxy_configuration_finished(mp))
+      configure_proxy(mp);
 
 
   } SMARTLIST_FOREACH_END(mp);
   } SMARTLIST_FOREACH_END(mp);
 }
 }
@@ -222,33 +307,55 @@ configure_proxy(managed_proxy_t *mp)
 
 
 /** Register server managed proxy <b>mp</b> transports to state */
 /** Register server managed proxy <b>mp</b> transports to state */
 static void
 static void
-register_server_proxy(const managed_proxy_t *mp)
+register_server_proxy(managed_proxy_t *mp)
 {
 {
-  if (mp->is_server) {
-    SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
-      save_transport_to_state(t->name,&t->addr,t->port); /* pass tor_addr_t? */
-    } SMARTLIST_FOREACH_END(t);
-  }
+  smartlist_t *sm_tmp = smartlist_create();
+
+  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+  SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
+    save_transport_to_state(t->name,&t->addr,t->port); /* pass tor_addr_t? */
+    smartlist_add(sm_tmp, tor_strdup(t->name));
+  } SMARTLIST_FOREACH_END(t);
+
+  smartlist_free(mp->transports);
+  mp->transports = sm_tmp;
 }
 }
 
 
 /** Register all the transports supported by client managed proxy
 /** Register all the transports supported by client managed proxy
  *  <b>mp</b> to the bridge subsystem. */
  *  <b>mp</b> to the bridge subsystem. */
 static void
 static void
-register_client_proxy(const managed_proxy_t *mp)
+register_client_proxy(managed_proxy_t *mp)
 {
 {
+  int r;
+  smartlist_t *sm_tmp = smartlist_create();
+
+  tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
   SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
   SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
-    if (transport_add(t)<0) {
+    r = transport_add(t);
+    switch (r) {
+    case -1:
       log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
       log_warn(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
       transport_free(t);
       transport_free(t);
-    } else {
+      break;
+    case 0:
       log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name);
       log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name);
+      smartlist_add(sm_tmp, tor_strdup(t->name));
+      break;
+    case 1:
+      log_warn(LD_GENERAL, "Succesfully registered transport %s", t->name);
+      smartlist_add(sm_tmp, tor_strdup(t->name));
+      transport_free(t);
+      break;
     }
     }
   } SMARTLIST_FOREACH_END(t);
   } SMARTLIST_FOREACH_END(t);
+
+  smartlist_free(mp->transports);
+  mp->transports = sm_tmp;
 }
 }
 
 
 /** Register the transports of managed proxy <b>mp</b>. */
 /** Register the transports of managed proxy <b>mp</b>. */
 static INLINE void
 static INLINE void
-register_proxy(const managed_proxy_t *mp)
+register_proxy(managed_proxy_t *mp)
 {
 {
   if (mp->is_server)
   if (mp->is_server)
     register_server_proxy(mp);
     register_server_proxy(mp);
@@ -256,18 +363,17 @@ register_proxy(const managed_proxy_t *mp)
     register_client_proxy(mp);
     register_client_proxy(mp);
 }
 }
 
 
-/** Free memory allocated by managed proxy <b>mp</b>.
- * If <b>also_free_transports</b> is set, also free the transports
- * associated with this managed proxy. */
+/** Free memory allocated by managed proxy <b>mp</b>. */
 static void
 static void
-managed_proxy_destroy_impl(managed_proxy_t *mp, int also_free_transports)
+managed_proxy_destroy(managed_proxy_t *mp)
 {
 {
-  /* transport_free() all its transports */
-  if (also_free_transports)
+  printf("Destroying mp %p\n", mp);
+  if (mp->conf_state != PT_PROTO_COMPLETED)
     SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
     SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+  else
+    SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
 
 
   /* free the transports smartlist */
   /* free the transports smartlist */
-  smartlist_clear(mp->transports);
   smartlist_free(mp->transports);
   smartlist_free(mp->transports);
 
 
   SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
   SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
@@ -277,31 +383,32 @@ managed_proxy_destroy_impl(managed_proxy_t *mp, int also_free_transports)
   smartlist_free(mp->transports_to_launch);
   smartlist_free(mp->transports_to_launch);
 
 
   /* remove it from the list of managed proxies */
   /* remove it from the list of managed proxies */
-  smartlist_remove(unconfigured_proxy_list, mp);
+  smartlist_remove(managed_proxy_list, mp);
 
 
   /* close its stdout stream */
   /* close its stdout stream */
-  fclose(mp->stdout);
+  if (mp->stdout)
+    fclose(mp->stdout);
 
 
   /* free the argv */
   /* free the argv */
   free_execve_args(mp->argv);
   free_execve_args(mp->argv);
 
 
+  if (mp->pid)
+    tor_terminate_process(mp->pid);
+
   tor_free(mp);
   tor_free(mp);
 }
 }
 
 
-
 /** Handle a configured or broken managed proxy <b>mp</b>. */
 /** Handle a configured or broken managed proxy <b>mp</b>. */
 static void
 static void
 handle_finished_proxy(managed_proxy_t *mp)
 handle_finished_proxy(managed_proxy_t *mp)
 {
 {
   switch (mp->conf_state) {
   switch (mp->conf_state) {
   case PT_PROTO_BROKEN: /* if broken: */
   case PT_PROTO_BROKEN: /* if broken: */
-    managed_proxy_destroy_with_transports(mp); /* destroy it and all its transports */
+    managed_proxy_destroy(mp); /* annihilate it. */
     break;
     break;
   case PT_PROTO_CONFIGURED: /* if configured correctly: */
   case PT_PROTO_CONFIGURED: /* if configured correctly: */
     register_proxy(mp); /* register transports */
     register_proxy(mp); /* register transports */
-    mp->conf_state = PT_PROTO_COMPLETED; /* mark it as completed, */
-    managed_proxy_destroy(mp); /* destroy the managed proxy struct,
-                                     keeping the transports intact */
+    mp->conf_state = PT_PROTO_COMPLETED; /* mark it as completed. */
     break;
     break;
   default:
   default:
     log_warn(LD_CONFIG, "Unfinished managed proxy in "
     log_warn(LD_CONFIG, "Unfinished managed proxy in "
@@ -309,7 +416,8 @@ handle_finished_proxy(managed_proxy_t *mp)
     tor_assert(0);
     tor_assert(0);
   }
   }
 
 
-  tor_assert(smartlist_len(unconfigured_proxy_list) >= 0);
+  unconfigured_proxies_n--;
+  tor_assert(unconfigured_proxies_n >= 0);
 }
 }
 
 
 /** Return true if the configuration of the managed proxy <b>mp</b> is
 /** Return true if the configuration of the managed proxy <b>mp</b> is
@@ -322,8 +430,7 @@ proxy_configuration_finished(const managed_proxy_t *mp)
 }
 }
 
 
 
 
-/** This function is called when a proxy sends an {S,C}METHODS DONE message,
- */
+/** This function is called when a proxy sends an {S,C}METHODS DONE message. */
 static void
 static void
 handle_methods_done(const managed_proxy_t *mp)
 handle_methods_done(const managed_proxy_t *mp)
 {
 {
@@ -694,6 +801,30 @@ set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
   tor_free(bindaddr);
   tor_free(bindaddr);
 }
 }
 
 
+/** Create and return a new managed proxy for <b>transport</b> using
+ *  <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server
+ *  managed proxy. */
+static managed_proxy_t *
+managed_proxy_create(const char *transport, char **proxy_argv, int is_server)
+{
+  managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+  mp->conf_state = PT_PROTO_INFANT;
+  mp->is_server = is_server;
+  mp->argv = proxy_argv;
+  mp->transports = smartlist_create();
+
+  mp->transports_to_launch = smartlist_create();
+  add_transport_to_proxy(transport, mp);
+
+  /* register the managed proxy */
+  if (!managed_proxy_list)
+    managed_proxy_list = smartlist_create();
+  smartlist_add(managed_proxy_list, mp);
+  unconfigured_proxies_n++;
+
+  return mp;
+}
+
 /** Register <b>transport</b> using proxy with <b>proxy_argv</b> to
 /** Register <b>transport</b> using proxy with <b>proxy_argv</b> to
  *  the managed proxy subsystem.
  *  the managed proxy subsystem.
  *  If <b>is_server</b> is true, then the proxy is a server proxy. */
  *  If <b>is_server</b> is true, then the proxy is a server proxy. */
@@ -705,21 +836,28 @@ pt_kickstart_proxy(const char *transport, char **proxy_argv, int is_server)
   mp = get_managed_proxy_by_argv(proxy_argv);
   mp = get_managed_proxy_by_argv(proxy_argv);
 
 
   if (!mp) { /* we haven't seen this proxy before */
   if (!mp) { /* we haven't seen this proxy before */
-    /* create a managed proxy */
-    managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
-    mp->conf_state = PT_PROTO_INFANT;
-    mp->is_server = is_server;
-    mp->argv = proxy_argv;
-    mp->transports = smartlist_create();
-
-    mp->transports_to_launch = smartlist_create();
-    add_transport_to_proxy(transport, mp);
+    managed_proxy_create(transport, proxy_argv, is_server);
+
+  } else { /* known proxy. add its transport to its transport list */
+    if (mp->got_hup) {
+      /* If the managed proxy we found is marked by a SIGHUP, it means
+         that it's not useless and should be kept. If it's marked for
+         removal, unmark it and increase the unconfigured proxies so
+         that we try to restart it if we need to. Afterwards, check if
+         a transport_t for 'transport' used to exist before the SIGHUP
+         and make sure it doesn't get deleted because we might reuse
+         it. */
+      if (mp->marked_for_removal) {
+        mp->marked_for_removal = 0;
+        unconfigured_proxies_n++;
+      }
+
+      transport_t *old_transport = NULL;
+      old_transport = transport_get_by_name(transport);
+      if (old_transport)
+        old_transport->marked_for_removal = 0;
+    }
 
 
-    /* register the managed proxy */
-    if (!unconfigured_proxy_list)
-      unconfigured_proxy_list = smartlist_create();
-    smartlist_add(unconfigured_proxy_list, mp);
-  } else { /* known proxy. just add transport to its transport list */
     add_transport_to_proxy(transport, mp);
     add_transport_to_proxy(transport, mp);
     free_execve_args(proxy_argv);
     free_execve_args(proxy_argv);
   }
   }
@@ -738,25 +876,66 @@ free_execve_args(char **arg)
   tor_free(arg);
   tor_free(arg);
 }
 }
 
 
+
+/** Tor will read its config, prepare the managed proxy list so that
+ *  proxies that are not used in the new config will shutdown, and
+ *  proxies that need to spawn more transports will do so. */
+void
+pt_prepare_proxy_list_for_config_read(void)
+{
+  if (!managed_proxy_list)
+    return;
+
+  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+    /* Destroy unconfigured proxies. */
+    if (mp->conf_state != PT_PROTO_COMPLETED) {
+        managed_proxy_destroy(mp);
+        unconfigured_proxies_n--;
+        continue;
+    }
+
+    tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+    mp->marked_for_removal = 1;
+    mp->got_hup = 1;
+    SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
+    smartlist_clear(mp->transports_to_launch);
+  } SMARTLIST_FOREACH_END(mp);
+
+  tor_assert(unconfigured_proxies_n == 0);
+}
+
+/** The tor config was read, destroy all managed proxies that were
+ *  marked by a previous call to prepare_proxy_list_for_config_read()
+ *  and are not used by the new config. */
+void
+sweep_proxy_list(void)
+{
+  if (!managed_proxy_list)
+    return;
+
+  SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+    if (mp->marked_for_removal) {
+      SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
+      managed_proxy_destroy(mp);
+    }
+  } SMARTLIST_FOREACH_END(mp);
+}
+
 /** Release all storage held by the pluggable transports subsystem. */
 /** Release all storage held by the pluggable transports subsystem. */
 void
 void
 pt_free_all(void)
 pt_free_all(void)
 {
 {
-  if (unconfigured_proxy_list) {
+  if (managed_proxy_list) {
     /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
     /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
        transports and it's the duty of the circuitbuild.c subsystem to
        transports and it's the duty of the circuitbuild.c subsystem to
        free them. Otherwise, it hasn't registered its transports yet
        free them. Otherwise, it hasn't registered its transports yet
        and we should free them here. */
        and we should free them here. */
-    SMARTLIST_FOREACH_BEGIN(unconfigured_proxy_list, managed_proxy_t *, mp) {
-      if (mp->conf_state == PT_PROTO_COMPLETED)
-        managed_proxy_destroy(mp);
-      else
-        managed_proxy_destroy_with_transports(mp);
-    } SMARTLIST_FOREACH_END(mp);
+    SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp,
+                      managed_proxy_destroy(mp));
 
 
-    smartlist_clear(unconfigured_proxy_list);
-    smartlist_free(unconfigured_proxy_list);
-    unconfigured_proxy_list=NULL;
+    smartlist_free(managed_proxy_list);
+    managed_proxy_list=NULL;
   }
   }
 }
 }
 
 

+ 41 - 1
src/or/transports.h

@@ -25,6 +25,9 @@ int pt_proxies_configuration_pending(void);
 
 
 void pt_free_all(void);
 void pt_free_all(void);
 
 
+void pt_prepare_proxy_list_for_config_read(void);
+void sweep_proxy_list(void);
+
 #ifdef PT_PRIVATE
 #ifdef PT_PRIVATE
 /** State of the managed proxy configuration protocol. */
 /** State of the managed proxy configuration protocol. */
 enum pt_proto_state {
 enum pt_proto_state {
@@ -47,8 +50,45 @@ typedef struct {
   FILE *stdout; /* a stream to its stdout
   FILE *stdout; /* a stream to its stdout
                    (closed in managed_proxy_destroy()) */
                    (closed in managed_proxy_destroy()) */
 
 
+  int pid; /* The Process ID this managed proxy is using. */
+
+  /** Boolean: We are re-parsing our config, and we are going to
+   * remove this managed proxy if we don't find it any transport
+   * plugins that use it. */
+  unsigned int marked_for_removal : 1;
+
+  /** Boolean: We got a SIGHUP while this proxy was running. We use
+   * this flag to signify that this proxy might need to be restarted
+   * so that it can listen for other transports according to the new
+   * torrc. */
+  unsigned int got_hup : 1;
+
   smartlist_t *transports_to_launch; /* transports to-be-launched by this proxy */
   smartlist_t *transports_to_launch; /* transports to-be-launched by this proxy */
-  smartlist_t *transports; /* list of transport_t this proxy spawned */
+
+  /* The 'transports' list contains all the transports this proxy has
+     launched.
+
+     Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase,
+     this smartlist contains a 'transport_t' for every transport it
+     has launched.
+
+     When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it
+     registers all its transports to the circuitbuild.c subsystem. At
+     that point the 'transport_t's are owned by the circuitbuild.c
+     subsystem.
+
+     To avoid carrying dangling 'transport_t's in this smartlist,
+     right before the managed_proxy_t reaches the PT_PROTO_COMPLETED
+     phase we replace all 'transport_t's with strings of their
+     transport names.
+
+     So, tl;dr:
+     When (conf_state != PT_PROTO_COMPLETED) this list carries
+     (transport_t *).
+     When (conf_state == PT_PROTO_COMPLETED) this list carries
+     (char *).
+   */
+  smartlist_t *transports;
 } managed_proxy_t;
 } managed_proxy_t;
 
 
 int parse_cmethod_line(const char *line, managed_proxy_t *mp);
 int parse_cmethod_line(const char *line, managed_proxy_t *mp);