subsysmgr.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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/err/torerr.h"
  8. #include "lib/log/log.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. /**
  13. * True iff we have checked tor_subsystems for consistency.
  14. **/
  15. static bool subsystem_array_validated = false;
  16. /**
  17. * True if a given subsystem is initialized. Expand this array if there
  18. * are more than this number of subsystems. (We'd rather not
  19. * dynamically allocate in this module.)
  20. **/
  21. static bool sys_initialized[128];
  22. /**
  23. * Exit with a raw assertion if the subsystems list is inconsistent;
  24. * initialize the subsystem_initialized array.
  25. **/
  26. static void
  27. check_and_setup(void)
  28. {
  29. if (subsystem_array_validated)
  30. return;
  31. raw_assert(ARRAY_LENGTH(sys_initialized) >= n_tor_subsystems);
  32. memset(sys_initialized, 0, sizeof(sys_initialized));
  33. int last_level = MIN_SUBSYS_LEVEL;
  34. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  35. const subsys_fns_t *sys = tor_subsystems[i];
  36. if (sys->level < MIN_SUBSYS_LEVEL || sys->level > MAX_SUBSYS_LEVEL) {
  37. fprintf(stderr, "BUG: Subsystem %s (at %u) has an invalid level %d. "
  38. "It is supposed to be between %d and %d (inclusive).\n",
  39. sys->name, i, sys->level, MIN_SUBSYS_LEVEL, MAX_SUBSYS_LEVEL);
  40. raw_assert_unreached_msg("There is a bug in subsystem_list.c");
  41. }
  42. if (sys->level < last_level) {
  43. fprintf(stderr, "BUG: Subsystem %s (at #%u) is in the wrong position. "
  44. "Its level is %d; but the previous subsystem's level was %d.\n",
  45. sys->name, i, sys->level, last_level);
  46. raw_assert_unreached_msg("There is a bug in subsystem_list.c");
  47. }
  48. last_level = sys->level;
  49. }
  50. subsystem_array_validated = true;
  51. }
  52. /**
  53. * Initialize all the subsystems; exit on failure.
  54. **/
  55. int
  56. subsystems_init(void)
  57. {
  58. return subsystems_init_upto(MAX_SUBSYS_LEVEL);
  59. }
  60. /**
  61. * Initialize all the subsystems whose level is less than or equal to
  62. * <b>target_level</b>; exit on failure.
  63. **/
  64. int
  65. subsystems_init_upto(int target_level)
  66. {
  67. check_and_setup();
  68. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  69. const subsys_fns_t *sys = tor_subsystems[i];
  70. if (!sys->supported)
  71. continue;
  72. if (sys->level > target_level)
  73. break;
  74. if (sys_initialized[i])
  75. continue;
  76. int r = 0;
  77. if (sys->initialize) {
  78. // Note that the logging subsystem is designed so that it does no harm
  79. // to log a message in an uninitialized state. These messages will be
  80. // discarded for now, however.
  81. log_debug(LD_GENERAL, "Initializing %s", sys->name);
  82. r = sys->initialize();
  83. }
  84. if (r < 0) {
  85. fprintf(stderr, "BUG: subsystem %s (at %u) initialization failed.\n",
  86. sys->name, i);
  87. raw_assert_unreached_msg("A subsystem couldn't be initialized.");
  88. }
  89. sys_initialized[i] = true;
  90. }
  91. return 0;
  92. }
  93. /**
  94. * Shut down all the subsystems.
  95. **/
  96. void
  97. subsystems_shutdown(void)
  98. {
  99. subsystems_shutdown_downto(MIN_SUBSYS_LEVEL - 1);
  100. }
  101. /**
  102. * Shut down all the subsystems whose level is above <b>target_level</b>.
  103. **/
  104. void
  105. subsystems_shutdown_downto(int target_level)
  106. {
  107. check_and_setup();
  108. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  109. const subsys_fns_t *sys = tor_subsystems[i];
  110. if (!sys->supported)
  111. continue;
  112. if (sys->level <= target_level)
  113. break;
  114. if (! sys_initialized[i])
  115. continue;
  116. if (sys->shutdown) {
  117. log_debug(LD_GENERAL, "Shutting down %s", sys->name);
  118. sys->shutdown();
  119. }
  120. sys_initialized[i] = false;
  121. }
  122. }
  123. /**
  124. * Run pre-fork code on all subsystems that declare any
  125. **/
  126. void
  127. subsystems_prefork(void)
  128. {
  129. check_and_setup();
  130. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  131. const subsys_fns_t *sys = tor_subsystems[i];
  132. if (!sys->supported)
  133. continue;
  134. if (! sys_initialized[i])
  135. continue;
  136. if (sys->prefork) {
  137. log_debug(LD_GENERAL, "Pre-fork: %s", sys->name);
  138. sys->prefork();
  139. }
  140. }
  141. }
  142. /**
  143. * Run post-fork code on all subsystems that declare any
  144. **/
  145. void
  146. subsystems_postfork(void)
  147. {
  148. check_and_setup();
  149. for (unsigned i = 0; i < n_tor_subsystems; ++i) {
  150. const subsys_fns_t *sys = tor_subsystems[i];
  151. if (!sys->supported)
  152. continue;
  153. if (! sys_initialized[i])
  154. continue;
  155. if (sys->postfork) {
  156. log_debug(LD_GENERAL, "Post-fork: %s", sys->name);
  157. sys->postfork();
  158. }
  159. }
  160. }
  161. /**
  162. * Run thread-cleanup code on all subsystems that declare any
  163. **/
  164. void
  165. subsystems_thread_cleanup(void)
  166. {
  167. check_and_setup();
  168. for (int i = (int)n_tor_subsystems - 1; i >= 0; --i) {
  169. const subsys_fns_t *sys = tor_subsystems[i];
  170. if (!sys->supported)
  171. continue;
  172. if (! sys_initialized[i])
  173. continue;
  174. if (sys->thread_cleanup) {
  175. log_debug(LD_GENERAL, "Thread cleanup: %s", sys->name);
  176. sys->thread_cleanup();
  177. }
  178. }
  179. }