subsysmgr.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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. #include "orconfig.h"
  6. #include "app/main/subsysmgr.h"
  7. #include "lib/dispatch/dispatch_naming.h"
  8. #include "lib/dispatch/msgtypes.h"
  9. #include "lib/err/torerr.h"
  10. #include "lib/log/log.h"
  11. #include "lib/malloc/malloc.h"
  12. #include "lib/pubsub/pubsub_build.h"
  13. #include "lib/pubsub/pubsub_connect.h"
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. /**
  18. * True iff we have checked tor_subsystems for consistency.
  19. **/
  20. static bool subsystem_array_validated = false;
  21. /**
  22. * True if a given subsystem is initialized. Expand this array if there
  23. * are more than this number of subsystems. (We'd rather not
  24. * dynamically allocate in this module.)
  25. **/
  26. static bool sys_initialized[128];
  27. /**
  28. * Exit with a raw assertion if the subsystems list is inconsistent;
  29. * initialize the subsystem_initialized array.
  30. **/
  31. static void
  32. check_and_setup(void)
  33. {
  34. if (subsystem_array_validated)
  35. return;
  36. raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
  37. memset(sys_initialized, 0, sizeof(sys_initialized));
  38. int last_level = MIN_SUBSYS_LEVEL;
  39. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  40. const subsys_fns_t *sys = tor_subsystems[i];
  41. if (sys->level < MIN_SUBSYS_LEVEL || sys->level > MAX_SUBSYS_LEVEL) {
  42. fprintf(stderr, "BUG: Subsystem %s (at %u) has an invalid level %d. "
  43. "It is supposed to be between %d and %d (inclusive).\n",
  44. sys->name, i, sys->level, MIN_SUBSYS_LEVEL, MAX_SUBSYS_LEVEL);
  45. raw_assert_unreached_msg("There is a bug in subsystem_list.c");
  46. }
  47. if (sys->level < last_level) {
  48. fprintf(stderr, "BUG: Subsystem %s (at #%u) is in the wrong position. "
  49. "Its level is %d; but the previous subsystem's level was %d.\n",
  50. sys->name, i, sys->level, last_level);
  51. raw_assert_unreached_msg("There is a bug in subsystem_list.c");
  52. }
  53. last_level = sys->level;
  54. }
  55. subsystem_array_validated = true;
  56. }
  57. /**
  58. * Initialize all the subsystems; exit on failure.
  59. **/
  60. int
  61. subsystems_init(void)
  62. {
  63. return subsystems_init_upto(MAX_SUBSYS_LEVEL);
  64. }
  65. /**
  66. * Initialize all the subsystems whose level is less than or equal to
  67. * <b>target_level</b>; exit on failure.
  68. **/
  69. int
  70. subsystems_init_upto(int target_level)
  71. {
  72. check_and_setup();
  73. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  74. const subsys_fns_t *sys = tor_subsystems[i];
  75. if (!sys->supported)
  76. continue;
  77. if (sys->level > target_level)
  78. break;
  79. if (sys_initialized[i])
  80. continue;
  81. int r = 0;
  82. if (sys->initialize) {
  83. // Note that the logging subsystem is designed so that it does no harm
  84. // to log a message in an uninitialized state. These messages will be
  85. // discarded for now, however.
  86. log_debug(LD_GENERAL, "Initializing %s", sys->name);
  87. r = sys->initialize();
  88. }
  89. if (r < 0) {
  90. fprintf(stderr, "BUG: subsystem %s (at %u) initialization failed.\n",
  91. sys->name, i);
  92. raw_assert_unreached_msg("A subsystem couldn't be initialized.");
  93. }
  94. sys_initialized[i] = true;
  95. }
  96. return 0;
  97. }
  98. /**
  99. * Add publish/subscribe relationships to <b>builder</b> for all
  100. * initialized subsystems of level no more than <b>target_level</b>.
  101. **/
  102. int
  103. subsystems_add_pubsub_upto(pubsub_builder_t *builder,
  104. int target_level)
  105. {
  106. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  107. const subsys_fns_t *sys = tor_subsystems[i];
  108. if (!sys->supported)
  109. continue;
  110. if (sys->level > target_level)
  111. break;
  112. if (! sys_initialized[i])
  113. continue;
  114. int r = 0;
  115. if (sys->add_pubsub) {
  116. subsys_id_t sysid = get_subsys_id(sys->name);
  117. raw_assert(sysid != ERROR_ID);
  118. pubsub_connector_t *connector;
  119. connector = pubsub_connector_for_subsystem(builder, sysid);
  120. r = sys->add_pubsub(connector);
  121. pubsub_connector_free(connector);
  122. }
  123. if (r < 0) {
  124. fprintf(stderr, "BUG: subsystem %s (at %u) could not connect to "
  125. "publish/subscribe system.", sys->name, sys->level);
  126. raw_assert_unreached_msg("A subsystem couldn't be connected.");
  127. }
  128. }
  129. return 0;
  130. }
  131. /**
  132. * Add publish/subscribe relationships to <b>builder</b> for all
  133. * initialized subsystems.
  134. **/
  135. int
  136. subsystems_add_pubsub(pubsub_builder_t *builder)
  137. {
  138. return subsystems_add_pubsub_upto(builder, MAX_SUBSYS_LEVEL);
  139. }
  140. /**
  141. * Shut down all the subsystems.
  142. **/
  143. void
  144. subsystems_shutdown(void)
  145. {
  146. subsystems_shutdown_downto(MIN_SUBSYS_LEVEL - 1);
  147. }
  148. /**
  149. * Shut down all the subsystems whose level is above <b>target_level</b>.
  150. **/
  151. void
  152. subsystems_shutdown_downto(int target_level)
  153. {
  154. check_and_setup();
  155. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  156. const subsys_fns_t *sys = tor_subsystems[i];
  157. if (!sys->supported)
  158. continue;
  159. if (sys->level <= target_level)
  160. break;
  161. if (! sys_initialized[i])
  162. continue;
  163. if (sys->shutdown) {
  164. log_debug(LD_GENERAL, "Shutting down %s", sys->name);
  165. sys->shutdown();
  166. }
  167. sys_initialized[i] = false;
  168. }
  169. }
  170. /**
  171. * Run pre-fork code on all subsystems that declare any
  172. **/
  173. void
  174. subsystems_prefork(void)
  175. {
  176. check_and_setup();
  177. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  178. const subsys_fns_t *sys = tor_subsystems[i];
  179. if (!sys->supported)
  180. continue;
  181. if (! sys_initialized[i])
  182. continue;
  183. if (sys->prefork) {
  184. log_debug(LD_GENERAL, "Pre-fork: %s", sys->name);
  185. sys->prefork();
  186. }
  187. }
  188. }
  189. /**
  190. * Run post-fork code on all subsystems that declare any
  191. **/
  192. void
  193. subsystems_postfork(void)
  194. {
  195. check_and_setup();
  196. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  197. const subsys_fns_t *sys = tor_subsystems[i];
  198. if (!sys->supported)
  199. continue;
  200. if (! sys_initialized[i])
  201. continue;
  202. if (sys->postfork) {
  203. log_debug(LD_GENERAL, "Post-fork: %s", sys->name);
  204. sys->postfork();
  205. }
  206. }
  207. }
  208. /**
  209. * Run thread-init code on all subsystems that declare any
  210. **/
  211. void
  212. subsystems_thread_init(void)
  213. {
  214. check_and_setup();
  215. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  216. const subsys_fns_t *sys = tor_subsystems[i];
  217. if (!sys->supported)
  218. continue;
  219. if (! sys_initialized[i])
  220. continue;
  221. if (sys->thread_init) {
  222. log_debug(LD_GENERAL, "Thread init: %s", sys->name);
  223. sys->thread_init();
  224. }
  225. }
  226. }
  227. /**
  228. * Run thread-cleanup code on all subsystems that declare any
  229. **/
  230. void
  231. subsystems_thread_cleanup(void)
  232. {
  233. check_and_setup();
  234. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  235. const subsys_fns_t *sys = tor_subsystems[i];
  236. if (!sys->supported)
  237. continue;
  238. if (! sys_initialized[i])
  239. continue;
  240. if (sys->thread_cleanup) {
  241. log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name);
  242. sys->thread_cleanup();
  243. }
  244. }
  245. }