startup.xml 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
  4. <section id="ser_startup" xmlns:xi="http://www.w3.org/2001/XInclude">
  5. <sectioninfo>
  6. <revhistory>
  7. <revision>
  8. <revnumber>$Revision$</revnumber>
  9. <date>$Date$</date>
  10. </revision>
  11. </revhistory>
  12. </sectioninfo>
  13. <title>The Server Startup</title>
  14. <para>
  15. The <function>main</function> function in file
  16. <filename>main.c</filename> is the first function called upon server
  17. startup. It's purpose is to initialize the server and enter main
  18. loop. The server initialization will be described in the following
  19. sections.
  20. </para>
  21. <para>
  22. Particular initialization steps are described in order in which they
  23. appear in <function>main</function> function.
  24. </para>
  25. <section id="signal_handlers">
  26. <title>Installation Of New Signal Handlers</title>
  27. <para>
  28. The first step in the initialization process is the installation of
  29. new signal handlers. We need our own signal handlers to be able to
  30. do graceful shutdown, print server statistics and so on. There is
  31. only one signal handler function which is function
  32. <function>sig_usr</function> in file <filename>main.c</filename>.
  33. </para>
  34. <para>
  35. The following signals are handled by the function: SIGINT, SIGPIPE,
  36. SIGUSR1, SIGCHLD, SIGTERM, SIGHUP and SIGUSR2.
  37. </para>
  38. </section> <!-- signal-installation -->
  39. <section id="cmdline_parameters">
  40. <title>Processing Command Line Parameters</title>
  41. <para>
  42. SER utilizes the <function>getopt</function>function to parse
  43. command line parameters. The function is extensively described in
  44. the man pages.
  45. </para>
  46. </section> <!-- cmd-line-params -->
  47. <section id="parser-init">
  48. <title>Parser Initialization</title>
  49. <para>
  50. SER contains a fast 32-bit parser. The parser uses pre-calculated
  51. hash table that needs to be filled in upon startup. The
  52. initialization is done here, there are two functions that do the
  53. job. Function <function>init_hfname_parser</function> initializes
  54. hash table in header field name parser and function
  55. <function>init_digest_parser</function> initializes hash table in
  56. digest authentication parser. The parser's internals will be
  57. described later.
  58. </para>
  59. </section> <!-- parser-init -->
  60. <section id="malloc_init">
  61. <title>Malloc Initialization</title>
  62. <para>
  63. To make SER even faster we decided to re-implement memory
  64. allocation routines. The new <function>malloc</function> better
  65. fits our needs and speeds up the server a lot. The memory
  66. management subsystem needs to be initialized upon server
  67. startup. The initialization mainly creates internal data structures
  68. and allocates memory region to be partitioned.
  69. </para>
  70. <important>
  71. <para>
  72. The memory allocation code must be initialized
  73. <emphasis>BEFORE</emphasis> any of its function is called !
  74. </para>
  75. </important>
  76. </section> <!-- malloc-init -->
  77. <section id="timer_init">
  78. <title>Timer Initialization</title>
  79. <para>
  80. Various subsystems of the server must be called periodically
  81. regardless of the incoming requests. That's what timer is
  82. for. Function <function>init_timer</function> initializes the timer
  83. subsystem. The function is called from <filename>main.c</filename>
  84. and can be found in <filename>timer.c</filename> The timer
  85. subsystem will be described later.
  86. </para>
  87. <warning>
  88. <para>
  89. Timer subsystem must be initialized before config file is parsed !
  90. </para>
  91. </warning>
  92. </section> <!-- timer-init -->
  93. <section id="fifo_init">
  94. <title>FIFO Initialization</title>
  95. <para>
  96. SER has built-in support for FIFO control. It means that the
  97. running server can accept commands over a FIFO special file (a
  98. named pipe). Function <function>register_core_fifo</function>
  99. initializes FIFO subsystem and registers basic commands, that are
  100. processed by the core itself. The function can be found in file
  101. <filename>fifo_server.c</filename>.
  102. </para>
  103. <para>
  104. The FIFO server will be described in another chapter.
  105. </para>
  106. </section> <!-- fifo-init -->
  107. <section id="builtin_modules">
  108. <title>Built-in Module Initialization</title>
  109. <para>
  110. Modules can be either loaded dynamically at runtime or compiled in statically. When a module
  111. is loaded at runtime, it is registered
  112. <footnote id="regfoot">
  113. <para>
  114. Module registration is a process when the core tries to find what functions and
  115. parameters are offered by the module.
  116. </para>
  117. </footnote>
  118. immediately with the core. When the module is compiled in
  119. statically, the registration<footnoteref linkend="regfoot"/> must be
  120. performed during the server startup. Function
  121. <function>register_builtin_modules</function> does the job.
  122. </para>
  123. </section> <!-- builtin-mod-reg -->
  124. <section id="ser_configuration">
  125. <title>Server Configuration</title>
  126. <para>
  127. The server is configured through a configuration file. The
  128. configuration file is C-Shell like script which defines how
  129. incoming requests should be processed. The file cannot be
  130. interpreted directly because that would be very slow. Instead of
  131. that the file is translated into an internal binary
  132. representation. The process is called compilation and will be
  133. described in the following sections.
  134. </para>
  135. <note>
  136. <para>
  137. The following sections only describe how the internal binary
  138. representation is being constructed from the config file. The
  139. way how the binary representation is used upon a request
  140. arrival will be described later.
  141. </para>
  142. </note>
  143. <para>The compilation can be divided in several steps:</para>
  144. <section id="lexical_analysis">
  145. <title>Lexical Analysis</title>
  146. <para>
  147. Lexical analysis is process of converting the input (the
  148. configuration file in this case) into a stream of tokens. A
  149. token is a set of characters that 'belong' together. A program
  150. that can turn the input into stream of tokens is called
  151. scanner. For example, when scanner encounters a number in the
  152. config file, it will produce token NUMBER.
  153. </para>
  154. <para>
  155. There is no need to implement the scanner from scratch, it can
  156. be done automatically. There is a utility called flex. Flex
  157. accepts a configuration file and generates scanner according to
  158. the configuration file. The configuration file for flex
  159. consists of several lines - each line describing one token. The
  160. tokens are described using regular expressions. For more
  161. details, see flex manual page or info documentation.
  162. </para>
  163. <para>
  164. Flex input file for the SER config file is in file
  165. <filename>cfg.lex</filename>. The file is processed by flex
  166. when the server is being compiled and the result is written in
  167. file <filename>lex.yy.c</filename>. The output file contains
  168. the scanner implemented in the C language.
  169. </para>
  170. </section> <!-- lex-analysis -->
  171. <section id="syntax_analysis">
  172. <title>Syntactical Analysis</title>
  173. <para>
  174. The second stage of configuration file processing is called
  175. syntactical analysis. Purpose of syntactical analysis is to
  176. check if the configuration file has been well formed, doesn't
  177. contain syntactical errors and perform various actions at
  178. various stages of the analysis. Program performing syntactical
  179. analysis is called parser.
  180. </para>
  181. <para>
  182. Structure of the configuration file is described using
  183. grammar. Grammar is a set of rules describing valid 'order' or
  184. 'combination' of tokens. If the file isn't conformable with
  185. it's grammar, it is syntactically invalid and cannot be further
  186. processed. In that case an error will be issued and the server
  187. will be aborted.
  188. </para>
  189. <para>
  190. There is a utility called yacc. Input of the utility is a file
  191. containing the grammar of the configuration file, in addition
  192. to the grammar, you can describe what action the parser should
  193. do at various stages of parsing. For example, you can instruct
  194. the parser to create a structure describing an IP address every
  195. time it finds an IP address in the configuration file and
  196. convert the address to its binary representation.
  197. </para>
  198. <para>For more information see yacc documentation.</para>
  199. <para>
  200. yacc creates the parser when the server is being compiled from
  201. the sources. Input file for yacc is
  202. <filename>cfg.y</filename>. The file contains grammar of the
  203. config file along with actions that create the binary
  204. representation of the file. Yacc will write its result into
  205. file <filename>cfg.tab.c</filename>. The file contains function
  206. <function>yyparse</function> which will parse the whole
  207. configuration file and construct the binary representation. For
  208. more information about the bison input file syntax see bison
  209. documentation.
  210. </para>
  211. </section> <!-- syntax-analysis -->
  212. <section id="config_structure">
  213. <title>Config File Structure</title>
  214. <para>
  215. The configuration file consist of three sections, each of the
  216. sections will be described separately.
  217. </para>
  218. <itemizedlist>
  219. <listitem>
  220. <para>
  221. <emphasis>Route Statement</emphasis> - The statement
  222. describes how incoming requests will be processed.
  223. When a request is received, commands in one or more
  224. "route" sections will be executed step by step. The
  225. config file must always contain one main "route"
  226. statement and may contain several additional "route"
  227. statements. Request processing always starts at the
  228. beginning of the main "route" statement. Additional
  229. "route" statements can be called from the main one or
  230. another additional "route" statements (It it similar to
  231. function calling).
  232. </para>
  233. </listitem>
  234. <listitem>
  235. <para>
  236. <emphasis>Assign Statement</emphasis> - There are many
  237. configuration variables across the server and this
  238. statement makes it possible to change their
  239. value. Generally it is a list of assignments, each
  240. assignment on a separate line.
  241. </para>
  242. </listitem>
  243. <listitem>
  244. <para>
  245. <emphasis>Module Statement</emphasis> - Additional
  246. functionality of the server is available through
  247. separate modules. Each module is a shared object that
  248. can be loaded at runtime. Modules can export functions,
  249. that can be called from the configuration file and
  250. variables, that can be configured from the config
  251. file. The module statement makes it possible to load
  252. modules and configure them. There are two commands in
  253. the statement - <function>loadmodule</function> and
  254. <function>modparam</function>. The first can load a
  255. module. The second one can configure module's internal
  256. variables.
  257. </para>
  258. </listitem>
  259. </itemizedlist>
  260. <para>
  261. In the following sections we will describe in detail how the
  262. three sections are being processed upon server startup.
  263. </para>
  264. <section id="route_statement">
  265. <title>Route Statement</title>
  266. <para>The following grammar snippet describes how the route statement is constructed</para>
  267. <programlisting>
  268. route_stm = "route" "{" actions "}"
  269. {
  270. $$ = push($3, &amp;rlist[DEFAULT_RT]);
  271. }
  272. actions = actions action { $$ = append_action($1, $2}; }
  273. | action { $$ = $1; }
  274. action = cmd SEMICOLON { $$ = $1; }
  275. | SEMICOLON { $$ = 0; }
  276. cmd = "forward" "(" host ")" { $$ = mk_action(FORWARD_T, STRING_ST, NUMBER_ST, $3, 0)
  277. | ...
  278. </programlisting>
  279. <para>
  280. A config file can contain one or more "route"
  281. statements. "route" statement without number will be
  282. executed first and is called the main route
  283. statement. There can be additional route statements
  284. identified by number, these additional route statements can
  285. be called from the main route statement or another
  286. additional route statements.
  287. </para>
  288. <para>
  289. Each route statement consists of a set of actions. Actions
  290. in the route statement are executed step by step in the
  291. same order in which they appear in the config file. Actions
  292. in the route statement are delimited by semicolon.
  293. </para>
  294. <para>
  295. Each action consists of one and only one command (cmd in
  296. the grammar). There are many types of commands defined. We
  297. don't list all of them here because the list would be too
  298. long and all the commands are processed in the same
  299. way. Therefore we show only one example (forward) and
  300. interested readers might look in <filename>cfg.y</filename>
  301. file for full list of available commands.
  302. </para>
  303. <para>
  304. Each rule in the grammar contains a section enclosed in
  305. curly braces. The section is the C code snippet that will
  306. be executed every time the parser recognizes that rule in
  307. the config file.
  308. </para>
  309. <para>
  310. For example, when the parser finds
  311. <function>forward</function> command,
  312. <function>mk_action</function> function (as specified in
  313. the grammar snippet above) will be called. The function
  314. creates a new structure with
  315. <structfield>type</structfield> field set to FORWARD_T
  316. representing the command. Pointer to the structure will be
  317. returned as the return value of the rule.
  318. </para>
  319. <para>
  320. The pointer propagates through <function>action</function>
  321. rule to <function>actions</function>
  322. rule. <function>Actions</function> rule will create linked
  323. list of all commands. The linked list will be then inserted
  324. into <structfield>rlist</structfield> table. (Function
  325. <function>push</function> in rule
  326. <function>route_stm</function>). Each element of the table
  327. represents one "route" statement of the config file.
  328. </para>
  329. <para>
  330. Each route statement of the configuration file will be
  331. represented by a linked list of all actions in the
  332. statement. Pointers to all the lists will be stored in
  333. rlist array. Additional route statements are identified by
  334. number. The number also serves as index to the array.
  335. </para>
  336. <para>
  337. When the core is about to execute route statement with
  338. number n, it will look in the array at position n. If the
  339. element at position n is not null then there is a linked
  340. list of commands and the commands will be executed step by
  341. step.
  342. </para>
  343. <para>
  344. Reply-Route statement is compiled in the same way. Main differences are:
  345. <itemizedlist>
  346. <listitem>
  347. <para>
  348. Reply-Route statement is executed when a SIP
  349. <emphasis>REPLY</emphasis> comes (not ,SIP
  350. <emphasis>REQUEST</emphasis>).
  351. </para>
  352. </listitem>
  353. <listitem>
  354. <para>
  355. Only subset of commands is allowed in the
  356. reply-route statement. (See file
  357. <filename>cfg.y</filename> for more details).
  358. </para>
  359. </listitem>
  360. <listitem>
  361. <para>Reply-route statement has it's own array of linked-lists.</para>
  362. </listitem>
  363. </itemizedlist>
  364. </para>
  365. </section> <!-- route-stm -->
  366. <section id="assign_statement">
  367. <title>Assign Statement</title>
  368. <para>
  369. The server contains many configuration variables. There is
  370. a section of the config file in which the variables can be
  371. assigned new value. The section is called The Assign
  372. Statement. The following grammar snippet describes how the
  373. section is constructed (only one example will be shown):
  374. </para>
  375. <programlisting>
  376. assign_stm = "children" '=' NUMBER { children_no=$3; }
  377. | "children" '=' error { yyerror("number expected"); }
  378. ...
  379. </programlisting>
  380. <para>
  381. The number in the config file is assigned to
  382. <varname>children_no</varname> variable. The second
  383. statement will be executed if the parameter is not number
  384. or is in invalid format and will issue an error and abort
  385. the server.
  386. </para>
  387. </section> <!-- assign-stm -->
  388. <section id="module_statement">
  389. <title>Module Statement</title>
  390. <para>
  391. The module statement allows module loading and
  392. configuration. There are two commands:
  393. </para>
  394. <itemizedlist>
  395. <listitem>
  396. <para>
  397. <emphasis>loadmodule</emphasis> - Load the
  398. specified module in form of a shared object. The
  399. shared object will be loaded using
  400. <function>dlopen</function>.
  401. </para>
  402. </listitem>
  403. <listitem>
  404. <para>
  405. <emphasis>modparam</emphasis> - It is possible to
  406. configure a module using this command. The command
  407. accepts 3 parameters: <emphasis>module
  408. name</emphasis>, <emphasis>variable name</emphasis>
  409. and <emphasis>variable value</emphasis>.
  410. </para>
  411. </listitem>
  412. </itemizedlist>
  413. <para>The following grammar snippet describes the module statement:</para>
  414. <programlisting>
  415. module_stm = "loadmodule" STRING
  416. {
  417. DBG("loading module %s\n", $2);
  418. if (load_module($2)!=0) {
  419. yyerror("failed to load module");
  420. }
  421. }
  422. | "loadmodule" error { yyerror("string expected"); }
  423. | "modparam" "(" STRING "," STRING "," STRING ")"
  424. {
  425. if (set_mod_param($3, $5, PARAM_STR|PARAM_STRING, $7) != 0) {
  426. yyerror("Can't set module parameter");
  427. }
  428. }
  429. | "modparam" "(" STRING "," STRING "," NUMBER ")"
  430. {
  431. if (set_mod_param($3, $5, PARAM_INT, (void*)$7) != 0) {
  432. yyerror("Can't set module parameter");
  433. }
  434. }
  435. | MODPARAM error { yyerror("Invalid arguments"); }
  436. </programlisting>
  437. <para>
  438. When the parser finds <function>loadmodule</function>
  439. command, it will execute statement in curly braces. The
  440. statement will call <function>load_module</function>
  441. function. The function will load the specified filename
  442. using <function>dlopen</function>. If
  443. <function>dlopen</function> was successful, the server will
  444. look for <structname>exports</structname> structure
  445. describing the module's interface and register the
  446. module. For more details see <link
  447. linkend="module_interface">module section</link>.
  448. </para>
  449. <para>
  450. If the parser finds <function>modparam</function> command,
  451. it will try to configure the specified variable in the
  452. specified module. The module must be loaded using
  453. <function>loadmodule</function> before
  454. <function>modparam</function> for the module can be used !
  455. Function <function>set_mod_param</function> will be called
  456. and will configure the variable in the specified module.
  457. </para>
  458. </section> <!-- module-stm -->
  459. </section> <!-- config-file-struct -->
  460. </section> <!-- ser-config -->
  461. <section id="iface_config">
  462. <title>Interface Configuration</title>
  463. <para>
  464. The server will try to obtain list of all configured interfaces of
  465. the host it is running on. If it fails the server tries to convert
  466. hostname to IP address and will use interface with the IP address
  467. only.
  468. </para>
  469. <para>
  470. Function <function>add_interfaces</function> will add all
  471. configured interfaces to the array.
  472. </para>
  473. <para>
  474. Try to convert all interface names to IP addresses, remove duplicates...
  475. </para>
  476. </section> <!-- iface-config -->
  477. <section id="daemon">
  478. <title>Turning into a Daemon</title>
  479. <para>
  480. When configured so, SER becomes a daemon during startup. A process
  481. is called daemon when it hasn't associated controlling
  482. terminal. See function <function>daemonize</function> in file
  483. <filename>main.c</filename> for more details. The function does
  484. the following:
  485. </para>
  486. <itemizedlist>
  487. <listitem>
  488. <para>
  489. <emphasis>chroot</emphasis> is performed if necessary. That
  490. ensures that the server will have access to a particular
  491. directory and its subdirectories only.
  492. </para>
  493. </listitem>
  494. <listitem>
  495. <para>
  496. Server's working directory is changed if the new working
  497. directory was specified (usually it is /).
  498. </para>
  499. </listitem>
  500. <listitem>
  501. <para>
  502. If command line parameter -g was used, the server's group
  503. ID is changed to that value.
  504. </para>
  505. </listitem>
  506. <listitem>
  507. <para>
  508. If command line parameter -u was used, the server's user ID
  509. is changed to that value.
  510. </para>
  511. </listitem>
  512. <listitem>
  513. <para>
  514. Perform <emphasis>fork</emphasis>, let the parent process
  515. exit. This ensures that we are not a group leader.
  516. </para>
  517. </listitem>
  518. <listitem>
  519. <para>
  520. Perform <emphasis>setsid</emphasis> to become a session
  521. leader and drop the controlling terminal.
  522. </para>
  523. </listitem>
  524. <listitem>
  525. <para>
  526. Fork again to drop group leadership.
  527. </para>
  528. </listitem>
  529. <listitem>
  530. <para>Create a pid file.</para>
  531. </listitem>
  532. <listitem>
  533. <para>Close all opened file descriptors.</para>
  534. </listitem>
  535. </itemizedlist>
  536. </section> <!-- daemon -->
  537. <section id="module_init">
  538. <title>Module Initialization</title>
  539. <para>
  540. The whole config file was parsed, all modules were loaded already
  541. and can be initialized now. A module can tell the core that it
  542. needs to be initialized by exporting <function>mod_init</function>
  543. function. <function>mod_init</function> function of all loaded
  544. modules will be called now.
  545. </para>
  546. </section> <!-- module-init -->
  547. <section id="routing_list_fixing">
  548. <title>Routing List Fixing</title>
  549. <para>
  550. After the whole routing list was parsed, there might be still
  551. places that can be further processed to speed-up the server. For
  552. example, several commands accept regular expression as one of their
  553. parameters. The regular expression can be compiled too and
  554. processing of compiled expression will be much faster.
  555. </para>
  556. <para>
  557. Another example might be string as parameter of a function. For
  558. example if you call <function>append_hf("Server: SIP Express
  559. Router\r\n")</function> from the routing script, the function will
  560. append a new header field after the last one. In this case, the
  561. function needs to know length of the string parameter. It could
  562. call <function>strlen</function> every time it is called, but that
  563. is not a very good idea because <function>strlen</function> would
  564. be called every time a message is processed and that is not
  565. necessary.
  566. </para>
  567. <para>
  568. Instead of that the length of the string parameter could be
  569. pre-calculated upon server startup, saved and reused later. The
  570. processing of the request will be faster because
  571. <function>append_hf</function> doesn't need to call
  572. <function>strlen</function> every time, I can just reuse the saved
  573. value.
  574. </para>
  575. <para>
  576. This can be used also for string to int conversions, hostname
  577. lookups, expression evaluation and so on.
  578. </para>
  579. <para>
  580. This process is called Routing List Fixing and will be done as one
  581. of last steps of the server startup.
  582. </para>
  583. <para>
  584. Every loaded module can export one or more functions. Each such
  585. function can have associated a fixup function, which should do
  586. fixing as described in this section. All such fixups of all loaded
  587. modules will be called here. That makes it possible for module
  588. functions to fix their parameters too if necessary.
  589. </para>
  590. </section> <!-- rt-list-fix -->
  591. <section id="stat-init">
  592. <title>Statistics Initialization</title>
  593. <para>
  594. If compiled-in, the core can produce some statistics about itself
  595. and traffic processed. The statistics subsystem gets initialized
  596. here, see function <function>init_stats</function>.
  597. </para>
  598. </section> <!-- stat-init -->
  599. <section id="socket_init">
  600. <title>Socket Initialization</title>
  601. <para>
  602. UDP socket initialization depends on <varname>dont_fork</varname>
  603. variable. If this variable is set (only one process will be
  604. processing incoming requests) and there are multiple listen
  605. interfaces, only the first one will be used. This mode is mainly
  606. for debugging.
  607. </para>
  608. <para>
  609. If the variable is not set, then sockets for all configured
  610. interfaces will be created and initialized. See function
  611. <function>udp_init</function> in file
  612. <filename>udp_server.c</filename> for more details.
  613. </para>
  614. </section> <!-- socke-init -->
  615. <section id="forking">
  616. <title>Forking</title>
  617. <para>
  618. The rest of the initialization process depends on value of
  619. <varname>dont_fork</varname> variable.
  620. <varname>dont_fork</varname> is a global variable defined in
  621. <filename>main.c</filename>. We will describe both variants
  622. separately.
  623. </para>
  624. <section id="dont_fork">
  625. <title><varname>dont_fork</varname> variable is set (not zero)</title>
  626. <para>
  627. If <varname>dont_fork</varname> variable is set, the server
  628. will be operating in special mode. There will be only one
  629. process processing incoming requests. This is very slow and was
  630. intended mainly for debugging purposes. The main process will
  631. be processing all incoming requests itself.
  632. </para>
  633. <para>
  634. The server still needs additional children:
  635. </para>
  636. <itemizedlist>
  637. <listitem>
  638. <para>
  639. One child is for the timer subsystem, the child will be
  640. processing timers independently of the main process.
  641. </para>
  642. </listitem>
  643. <listitem>
  644. <para>
  645. FIFO server will spawn another child if enabled. The
  646. child will be processing all commands coming through
  647. the fifo interface.
  648. </para>
  649. </listitem>
  650. <listitem>
  651. <para>If SNMP support was enabled, another child will be created.</para>
  652. </listitem>
  653. </itemizedlist>
  654. <para>
  655. The following initialization will be performed in dont fork
  656. mode. (look into function <function>main_loop</function> in
  657. file <filename>main.c</filename>.
  658. </para>
  659. <itemizedlist>
  660. <listitem>
  661. <para>Another child will be forked for the timer subsystem.</para>
  662. </listitem>
  663. <listitem>
  664. <para>
  665. Initialize the FIFO server if enabled, this will fork
  666. another child. For more info about the FIFO server,
  667. see section The FIFO server.
  668. </para>
  669. </listitem>
  670. <listitem>
  671. <para>
  672. Call <function>init_child(0).</function> The function
  673. performs per-child specific initialization of all
  674. loaded modules. A module can be initialized though
  675. <function>mod_init</function> function. The function
  676. is called <emphasis>BEFORE</emphasis> the server forks
  677. and thus is common for all children.
  678. </para>
  679. <para>
  680. If there is anything, that needs to be initialized in
  681. every child separately (for example if each child needs
  682. to open its own file descriptor), it cannot be done in
  683. <function>mod_init</function>. To make such
  684. initialization possible, a module can export another
  685. initialization function called
  686. <function>init_child</function>. The function will be
  687. called in all children <emphasis>AFTER</emphasis> fork
  688. of the server.
  689. </para>
  690. <para>
  691. And since we are in "dont fork" mode and there will no
  692. children processing requests (remember the main process
  693. will be processing all requests), the
  694. <function>init_child</function> wouldn't be called.
  695. </para>
  696. <para>
  697. That would be bad, because
  698. <function>child_init</function> might do some
  699. initialization that must be done otherwise modules
  700. might not work properly.
  701. </para>
  702. <para>
  703. To make sure that module initialization is complete we
  704. will call <function>init_child</function> here for the
  705. main process even if we are not going to fork.
  706. </para>
  707. </listitem>
  708. </itemizedlist>
  709. <para>
  710. That's it. Everything has been initialized properly and as the
  711. last step we will call <function>udp_rcv_loop</function> which
  712. is the main loop function. The function will be described
  713. later.
  714. </para>
  715. </section> <!-- dont-fork-set -->
  716. <section id="dont_fork_not_set">
  717. <title><varname>dont_fork</varname> is not set (zero)</title>
  718. <para>
  719. <varname>dont_fork</varname> is not set. That means that the
  720. server will fork children and the children will be processing
  721. incoming requests. How many children will be created depends on
  722. the configuration (<varname>children</varname> variable). The
  723. main process will be sleeping and handling signals only.
  724. </para>
  725. <para>
  726. The main process will then initialize the FIFO server. The FIFO
  727. server needs another child to handle communication over FIFO
  728. and thus another child will be created. The FIFO server will be
  729. described in more detail later.
  730. </para>
  731. <para>
  732. Then the main process will perform another fork for the timer
  733. attendant. The child will take care of timer lists and execute
  734. specified function when a timer hits.
  735. </para>
  736. <para>
  737. The main process is now completely initialized, it will sleep
  738. in <function>pause</function> function until a signal comes and
  739. call <function>handle_sigs</function> when such condition
  740. occurs.
  741. </para>
  742. <para>
  743. The following initialization will be performed by each child
  744. separately:
  745. </para>
  746. <para>
  747. Each child executes <function>init_child</function>
  748. function. The function will sequentially call
  749. <function>child_init</function> functions of all loaded
  750. modules.
  751. </para>
  752. <para>
  753. Because the function is called in each child separately, it can
  754. initialize per-child specific data. For example if a module
  755. needs to communicate with database, it must open a database
  756. connection. If the connection would be opened in
  757. <function>mod_init</function> function, all the children would
  758. share the same connection and locking would be necessary to
  759. avoid conflicts. On the other hand if the connection was opened
  760. in <function>child_init</function> function, each child will
  761. have its own connection and concurrency conflicts will be
  762. handled by the database server.
  763. </para>
  764. <para>
  765. And last, but not least, each child executes
  766. <function>udp_rcv_loop</function> function which contains the
  767. main loop logic.
  768. </para>
  769. </section> <!-- dont-fork-not-set -->
  770. </section> <!-- forking -->
  771. </section>