tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit 17c9ab79510c2c2d729c74420c3d10af6a2e68d7
parent a40b58b3c9dfc45886d5213dda5a02701fbeaeeb
Author: mischief <mischief@offblast.org>
Date:   Fri, 23 Jan 2026 16:51:58 -0800

transports: handle process death better

today tor will die with an assertion if a transport process dies before
configuration is complete, so remove that assertion and just warn.

additionally, launch transports via timed event callback, to prevent
spamming if the process is repeatedly dying.

Diffstat:
Msrc/feature/client/transports.c | 40+++++++++++++++++++++++++++++++++++-----
Msrc/feature/client/transports.h | 5+++++
2 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c @@ -90,6 +90,7 @@ **/ #include "lib/string/printf.h" +#include "lib/evloop/compat_libevent.h" #define PT_PRIVATE #include "core/or/or.h" #include "feature/client/bridges.h" @@ -517,7 +518,8 @@ proxy_prepare_for_restart(managed_proxy_t *mp) { transport_t *t_tmp = NULL; - tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + log_warn(LD_PT, "Managed proxy at '%s' died in state %s", + mp->argv[0], managed_proxy_state_to_string(mp->conf_state)); /* destroy the process handle and terminate the process. */ if (mp->process) { @@ -543,9 +545,11 @@ proxy_prepare_for_restart(managed_proxy_t *mp) mp->proxy_uri = get_pt_proxy_uri(); mp->proxy_supported = 0; + if (mp->conf_state == PT_PROTO_COMPLETED) + unconfigured_proxies_n++; + /* flag it as an infant proxy so that it gets launched on next tick */ managed_proxy_set_state(mp, PT_PROTO_INFANT); - unconfigured_proxies_n++; } /** Launch managed proxy <b>mp</b>. */ @@ -643,6 +647,23 @@ pt_configure_remaining_proxies(void) mark_my_descriptor_dirty("configured managed proxies"); } +/** event callback to launch managed proxy after a delay */ +STATIC void +launch_proxy_ev(mainloop_event_t *event, void *v) +{ + managed_proxy_t *mp = v; + + (void) event; + + tor_assert(mp); + tor_assert(mp->conf_state == PT_PROTO_WAITING); + + if (launch_managed_proxy(mp) < 0) { /* launch fail */ + managed_proxy_set_state(mp, PT_PROTO_FAILED_LAUNCH); + handle_finished_proxy(mp); + } +} + /** Attempt to continue configuring managed proxy <b>mp</b>. * Return 1 if the transport configuration finished, and return 0 * otherwise (if we still have more configuring to do for this @@ -652,10 +673,13 @@ configure_proxy(managed_proxy_t *mp) { /* if we haven't launched the proxy yet, do it now */ if (mp->conf_state == PT_PROTO_INFANT) { - if (launch_managed_proxy(mp) < 0) { /* launch fail */ - managed_proxy_set_state(mp, PT_PROTO_FAILED_LAUNCH); - handle_finished_proxy(mp); + const struct timeval delay_tv = { 1, 0 }; + if (!mp->process_launch_ev) { + mp->process_launch_ev = mainloop_event_new(launch_proxy_ev, mp); } + mainloop_event_schedule(mp->process_launch_ev, &delay_tv); + managed_proxy_set_state(mp, PT_PROTO_WAITING); + return 0; } @@ -756,6 +780,9 @@ managed_proxy_destroy(managed_proxy_t *mp, process_terminate(mp->process); } + if (mp->process_launch_ev) + mainloop_event_free(mp->process_launch_ev); + tor_free(mp); } @@ -828,6 +855,7 @@ handle_finished_proxy(managed_proxy_t *mp) managed_proxy_set_state(mp, PT_PROTO_COMPLETED); break; case PT_PROTO_INFANT: + case PT_PROTO_WAITING: case PT_PROTO_LAUNCHED: case PT_PROTO_ACCEPTING_METHODS: case PT_PROTO_COMPLETED: @@ -2205,6 +2233,8 @@ managed_proxy_state_to_string(enum pt_proto_state state) switch (state) { case PT_PROTO_INFANT: return "Infant"; + case PT_PROTO_WAITING: + return "Waiting"; case PT_PROTO_LAUNCHED: return "Launched"; case PT_PROTO_ACCEPTING_METHODS: diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h @@ -77,6 +77,7 @@ char *tor_escape_str_for_pt_args(const char *string, /** State of the managed proxy configuration protocol. */ enum pt_proto_state { PT_PROTO_INFANT, /* was just born */ + PT_PROTO_WAITING, /* waiting to be launched */ PT_PROTO_LAUNCHED, /* was just launched */ PT_PROTO_ACCEPTING_METHODS, /* accepting methods */ PT_PROTO_CONFIGURED, /* configured successfully */ @@ -101,6 +102,9 @@ typedef struct { /* A pointer to the process of this managed proxy. */ struct process_t *process; + /* timer event to launch proxy */ + struct mainloop_event_t *process_launch_ev; + /** 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. */ @@ -150,6 +154,7 @@ STATIC void managed_proxy_destroy(managed_proxy_t *mp, STATIC managed_proxy_t *managed_proxy_create(const smartlist_t *transport_list, char **proxy_argv, int is_server); +STATIC void launch_proxy_ev(struct mainloop_event_t *event, void *v); STATIC int configure_proxy(managed_proxy_t *mp); STATIC char* get_pt_proxy_uri(void);