tor  0.4.2.0-alpha-dev
subsysmgr.c
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 #include "orconfig.h"
7 #include "app/main/subsysmgr.h"
8 
9 #include "lib/dispatch/dispatch_naming.h"
10 #include "lib/dispatch/msgtypes.h"
11 #include "lib/err/torerr.h"
12 #include "lib/log/log.h"
13 #include "lib/malloc/malloc.h"
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
24 static bool subsystem_array_validated = false;
25 
31 static bool sys_initialized[128];
32 
37 static void
38 check_and_setup(void)
39 {
40  if (subsystem_array_validated)
41  return;
42 
43  raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
44  memset(sys_initialized, 0, sizeof(sys_initialized));
45 
46  int last_level = MIN_SUBSYS_LEVEL;
47 
48  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
49  const subsys_fns_t *sys = tor_subsystems[i];
50  if (sys->level < MIN_SUBSYS_LEVEL || sys->level > MAX_SUBSYS_LEVEL) {
51  fprintf(stderr, "BUG: Subsystem %s (at %u) has an invalid level %d. "
52  "It is supposed to be between %d and %d (inclusive).\n",
53  sys->name, i, sys->level, MIN_SUBSYS_LEVEL, MAX_SUBSYS_LEVEL);
54  raw_assert_unreached_msg("There is a bug in subsystem_list.c");
55  }
56  if (sys->level < last_level) {
57  fprintf(stderr, "BUG: Subsystem %s (at #%u) is in the wrong position. "
58  "Its level is %d; but the previous subsystem's level was %d.\n",
59  sys->name, i, sys->level, last_level);
60  raw_assert_unreached_msg("There is a bug in subsystem_list.c");
61  }
62  last_level = sys->level;
63  }
64 
65  subsystem_array_validated = true;
66 }
67 
71 int
72 subsystems_init(void)
73 {
74  return subsystems_init_upto(MAX_SUBSYS_LEVEL);
75 }
76 
81 int
82 subsystems_init_upto(int target_level)
83 {
84  check_and_setup();
85 
86  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
87  const subsys_fns_t *sys = tor_subsystems[i];
88  if (!sys->supported)
89  continue;
90  if (sys->level > target_level)
91  break;
92  if (sys_initialized[i])
93  continue;
94  int r = 0;
95  if (sys->initialize) {
96  // Note that the logging subsystem is designed so that it does no harm
97  // to log a message in an uninitialized state. These messages will be
98  // discarded for now, however.
99  log_debug(LD_GENERAL, "Initializing %s", sys->name);
100  r = sys->initialize();
101  }
102  if (r < 0) {
103  fprintf(stderr, "BUG: subsystem %s (at %u) initialization failed.\n",
104  sys->name, i);
105  raw_assert_unreached_msg("A subsystem couldn't be initialized.");
106  }
107  sys_initialized[i] = true;
108  }
109 
110  return 0;
111 }
112 
117 int
118 subsystems_add_pubsub_upto(pubsub_builder_t *builder,
119  int target_level)
120 {
121  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
122  const subsys_fns_t *sys = tor_subsystems[i];
123  if (!sys->supported)
124  continue;
125  if (sys->level > target_level)
126  break;
127  if (! sys_initialized[i])
128  continue;
129  int r = 0;
130  if (sys->add_pubsub) {
131  subsys_id_t sysid = get_subsys_id(sys->name);
132  raw_assert(sysid != ERROR_ID);
133  pubsub_connector_t *connector;
134  connector = pubsub_connector_for_subsystem(builder, sysid);
135  r = sys->add_pubsub(connector);
136  pubsub_connector_free(connector);
137  }
138  if (r < 0) {
139  fprintf(stderr, "BUG: subsystem %s (at %u) could not connect to "
140  "publish/subscribe system.", sys->name, sys->level);
141  raw_assert_unreached_msg("A subsystem couldn't be connected.");
142  }
143  }
144 
145  return 0;
146 }
147 
152 int
153 subsystems_add_pubsub(pubsub_builder_t *builder)
154 {
155  return subsystems_add_pubsub_upto(builder, MAX_SUBSYS_LEVEL);
156 }
157 
161 void
162 subsystems_shutdown(void)
163 {
164  subsystems_shutdown_downto(MIN_SUBSYS_LEVEL - 1);
165 }
166 
170 void
171 subsystems_shutdown_downto(int target_level)
172 {
173  check_and_setup();
174 
175  for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
176  const subsys_fns_t *sys = tor_subsystems[i];
177  if (!sys->supported)
178  continue;
179  if (sys->level <= target_level)
180  break;
181  if (! sys_initialized[i])
182  continue;
183  if (sys->shutdown) {
184  log_debug(LD_GENERAL, "Shutting down %s", sys->name);
185  sys->shutdown();
186  }
187  sys_initialized[i] = false;
188  }
189 }
190 
194 void
195 subsystems_prefork(void)
196 {
197  check_and_setup();
198 
199  for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
200  const subsys_fns_t *sys = tor_subsystems[i];
201  if (!sys->supported)
202  continue;
203  if (! sys_initialized[i])
204  continue;
205  if (sys->prefork) {
206  log_debug(LD_GENERAL, "Pre-fork: %s", sys->name);
207  sys->prefork();
208  }
209  }
210 }
211 
215 void
216 subsystems_postfork(void)
217 {
218  check_and_setup();
219 
220  for (unsigned i = 0; i < n_tor_subsystems; ++i) {
221  const subsys_fns_t *sys = tor_subsystems[i];
222  if (!sys->supported)
223  continue;
224  if (! sys_initialized[i])
225  continue;
226  if (sys->postfork) {
227  log_debug(LD_GENERAL, "Post-fork: %s", sys->name);
228  sys->postfork();
229  }
230  }
231 }
232 
236 void
237 subsystems_thread_cleanup(void)
238 {
239  check_and_setup();
240 
241  for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
242  const subsys_fns_t *sys = tor_subsystems[i];
243  if (!sys->supported)
244  continue;
245  if (! sys_initialized[i])
246  continue;
247  if (sys->thread_cleanup) {
248  log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name);
249  sys->thread_cleanup();
250  }
251  }
252 }
int level
Definition: subsys.h:41
struct pubsub_connector_t pubsub_connector_t
#define ERROR_ID
Definition: msgtypes.h:34
struct pubsub_builder_t pubsub_builder_t
Definition: pubsub_build.h:28
#define LD_GENERAL
Definition: log.h:60
bool supported
Definition: subsys.h:34
Headers for util_malloc.c.
Types used for messages in the dispatcher code.
int(* initialize)(void)
Definition: subsys.h:56
int(* add_pubsub)(struct pubsub_connector_t *)
Definition: subsys.h:61
void(* postfork)(void)
Definition: subsys.h:71
void(* shutdown)(void)
Definition: subsys.h:84
void(* thread_cleanup)(void)
Definition: subsys.h:77
uint16_t subsys_id_t
Definition: msgtypes.h:22
#define ARRAY_LENGTH(x)
Headers for torerr.c.
const char * name
Definition: subsys.h:28
pubsub_connector_t * pubsub_connector_for_subsystem(pubsub_builder_t *builder, subsys_id_t subsys)
Definition: pubsub_build.c:89
void(* prefork)(void)
Definition: subsys.h:66
Headers for log.c.
Header for functions that add relationships to a pubsub builder.
Header used for constructing the OO publish-subscribe facility.
#define pubsub_connector_free(c)
Definition: pubsub_build.h:67