s3-spoolssd: Use parametric option for prefork parameters
[mat/samba.git] / source3 / printing / spoolssd.c
1 /*
2    Unix SMB/Netbios implementation.
3    SPOOLSS Daemon
4    Copyright (C) Simo Sorce 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "serverid.h"
21 #include "smbd/smbd.h"
22
23 #include "messages.h"
24 #include "include/printing.h"
25 #include "printing/nt_printing_migrate_internal.h"
26 #include "ntdomain.h"
27 #include "librpc/gen_ndr/srv_winreg.h"
28 #include "librpc/gen_ndr/srv_spoolss.h"
29 #include "rpc_server/rpc_server.h"
30 #include "rpc_server/rpc_ep_register.h"
31 #include "rpc_server/spoolss/srv_spoolss_nt.h"
32 #include "librpc/rpc/dcerpc_ep.h"
33 #include "lib/server_prefork.h"
34
35 #define SPOOLSS_PIPE_NAME "spoolss"
36 #define DAEMON_NAME "spoolssd"
37
38 #define SPOOLSS_MIN_CHILDREN 5
39 #define SPOOLSS_MAX_CHILDREN 25
40 #define SPOOLSS_SPAWN_RATE 5
41 #define SPOOLSS_MIN_LIFE 60 /* 1 minute minimum life time */
42
43 static int spoolss_min_children;
44 static int spoolss_max_children;
45 static int spoolss_spawn_rate;
46
47 static void spoolss_prefork_config(void)
48 {
49         const char *prefork_str;
50         int min, max, rate;
51         bool use_defaults = false;
52         int ret;
53
54         prefork_str = lp_parm_const_string(GLOBAL_SECTION_SNUM,
55                                            "spoolssd", "prefork", "none");
56         if (strcmp(prefork_str, "none") == 0) {
57                 use_defaults = true;
58         } else {
59                 ret = sscanf(prefork_str, "%d:%d:%d", &min, &max, &rate);
60                 if (ret != 3) {
61                         DEBUG(0, ("invalid format for spoolssd:prefork!\n"));
62                         use_defaults = true;
63                 }
64         }
65
66         if (use_defaults) {
67                 spoolss_min_children = SPOOLSS_MIN_CHILDREN;
68                 spoolss_max_children = SPOOLSS_MAX_CHILDREN;
69                 spoolss_spawn_rate = SPOOLSS_SPAWN_RATE;
70         } else {
71                 spoolss_min_children = min;
72                 spoolss_max_children = max;
73                 spoolss_spawn_rate = rate;
74         }
75 }
76
77 void start_spoolssd(struct tevent_context *ev_ctx,
78                     struct messaging_context *msg_ctx);
79
80 static void spoolss_reopen_logs(void)
81 {
82         char *lfile = lp_logfile();
83         int rc;
84
85         if (lfile == NULL || lfile[0] == '\0') {
86                 rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
87                 if (rc > 0) {
88                         lp_set_logfile(lfile);
89                         SAFE_FREE(lfile);
90                 }
91         } else {
92                 if (strstr(lfile, DAEMON_NAME) == NULL) {
93                         rc = asprintf(&lfile, "%s.%s", lp_logfile(), DAEMON_NAME);
94                         if (rc > 0) {
95                                 lp_set_logfile(lfile);
96                                 SAFE_FREE(lfile);
97                         }
98                 }
99         }
100
101         reopen_logs();
102 }
103
104 static void smb_conf_updated(struct messaging_context *msg,
105                              void *private_data,
106                              uint32_t msg_type,
107                              struct server_id server_id,
108                              DATA_BLOB *data)
109 {
110         struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
111                                                              struct tevent_context);
112
113         DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
114         change_to_root_user();
115         reload_printers(ev_ctx, msg);
116         spoolss_reopen_logs();
117         spoolss_prefork_config();
118 }
119
120 static void spoolss_sig_term_handler(struct tevent_context *ev,
121                                      struct tevent_signal *se,
122                                      int signum,
123                                      int count,
124                                      void *siginfo,
125                                      void *private_data)
126 {
127         exit_server_cleanly("termination signal");
128 }
129
130 static void spoolss_setup_sig_term_handler(struct tevent_context *ev_ctx)
131 {
132         struct tevent_signal *se;
133
134         se = tevent_add_signal(ev_ctx,
135                                ev_ctx,
136                                SIGTERM, 0,
137                                spoolss_sig_term_handler,
138                                NULL);
139         if (!se) {
140                 exit_server("failed to setup SIGTERM handler");
141         }
142 }
143
144 static void spoolss_sig_hup_handler(struct tevent_context *ev,
145                                     struct tevent_signal *se,
146                                     int signum,
147                                     int count,
148                                     void *siginfo,
149                                     void *pvt)
150 {
151         struct messaging_context *msg_ctx;
152
153         msg_ctx = talloc_get_type_abort(pvt, struct messaging_context);
154
155         change_to_root_user();
156         DEBUG(1,("Reloading printers after SIGHUP\n"));
157         reload_printers(ev, msg_ctx);
158         spoolss_reopen_logs();
159 }
160
161 static void spoolss_setup_sig_hup_handler(struct tevent_context *ev_ctx,
162                                           struct messaging_context *msg_ctx)
163 {
164         struct tevent_signal *se;
165
166         se = tevent_add_signal(ev_ctx,
167                                ev_ctx,
168                                SIGHUP, 0,
169                                spoolss_sig_hup_handler,
170                                msg_ctx);
171         if (!se) {
172                 exit_server("failed to setup SIGHUP handler");
173         }
174 }
175
176 static bool spoolss_init_cb(void *ptr)
177 {
178         struct messaging_context *msg_ctx = talloc_get_type_abort(
179                 ptr, struct messaging_context);
180
181         return nt_printing_tdb_migrate(msg_ctx);
182 }
183
184 static bool spoolss_shutdown_cb(void *ptr)
185 {
186         srv_spoolss_cleanup();
187
188         return true;
189 }
190
191 /* Childrens */
192
193 struct spoolss_chld_sig_hup_ctx {
194         struct messaging_context *msg_ctx;
195         struct pf_worker_data *pf;
196 };
197
198 static void spoolss_chld_sig_hup_handler(struct tevent_context *ev,
199                                          struct tevent_signal *se,
200                                          int signum,
201                                          int count,
202                                          void *siginfo,
203                                          void *pvt)
204 {
205         struct spoolss_chld_sig_hup_ctx *shc;
206
207         shc = talloc_get_type_abort(pvt, struct spoolss_chld_sig_hup_ctx);
208
209         /* avoid wasting CPU cycles if we are going to exit soon anyways */
210         if (shc->pf != NULL &&
211             shc->pf->cmds == PF_SRV_MSG_EXIT) {
212                 return;
213         }
214
215         change_to_root_user();
216         DEBUG(1,("Reloading printers after SIGHUP\n"));
217         reload_printers(ev, shc->msg_ctx);
218         spoolss_reopen_logs();
219 }
220
221 static bool spoolss_setup_chld_hup_handler(struct tevent_context *ev_ctx,
222                                            struct pf_worker_data *pf,
223                                            struct messaging_context *msg_ctx)
224 {
225         struct spoolss_chld_sig_hup_ctx *shc;
226         struct tevent_signal *se;
227
228         shc = talloc(ev_ctx, struct spoolss_chld_sig_hup_ctx);
229         if (!shc) {
230                 DEBUG(1, ("failed to setup SIGHUP handler"));
231                 return false;
232         }
233         shc->pf = pf;
234         shc->msg_ctx = msg_ctx;
235
236         se = tevent_add_signal(ev_ctx,
237                                ev_ctx,
238                                SIGHUP, 0,
239                                spoolss_chld_sig_hup_handler,
240                                shc);
241         if (!se) {
242                 DEBUG(1, ("failed to setup SIGHUP handler"));
243                 return false;
244         }
245
246         return true;
247 }
248
249 static bool spoolss_child_init(struct tevent_context *ev_ctx,
250                                         struct pf_worker_data *pf)
251 {
252         NTSTATUS status;
253         struct rpc_srv_callbacks spoolss_cb;
254         struct messaging_context *msg_ctx = server_messaging_context();
255         bool ok;
256
257         status = reinit_after_fork(msg_ctx, ev_ctx,
258                                    procid_self(), true);
259         if (!NT_STATUS_IS_OK(status)) {
260                 DEBUG(0,("reinit_after_fork() failed\n"));
261                 smb_panic("reinit_after_fork() failed");
262         }
263
264         spoolss_reopen_logs();
265
266         ok = spoolss_setup_chld_hup_handler(ev_ctx, pf, msg_ctx);
267         if (!ok) {
268                 return false;
269         }
270
271         if (!serverid_register(procid_self(), FLAG_MSG_GENERAL)) {
272                 return false;
273         }
274
275         if (!locking_init()) {
276                 return false;
277         }
278
279         messaging_register(msg_ctx, ev_ctx,
280                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
281
282         /* try to reinit rpc queues */
283         spoolss_cb.init = spoolss_init_cb;
284         spoolss_cb.shutdown = spoolss_shutdown_cb;
285         spoolss_cb.private_data = msg_ctx;
286
287         status = rpc_winreg_init(NULL);
288         if (!NT_STATUS_IS_OK(status)) {
289                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
290                           nt_errstr(status)));
291                 return false;
292         }
293
294         status = rpc_spoolss_init(&spoolss_cb);
295         if (!NT_STATUS_IS_OK(status)) {
296                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
297                           nt_errstr(status)));
298                 return false;
299         }
300
301         reload_printers(ev_ctx, msg_ctx);
302
303         return true;
304 }
305
306 struct spoolss_children_data {
307         struct tevent_context *ev_ctx;
308         struct messaging_context *msg_ctx;
309         struct pf_worker_data *pf;
310         int listen_fd;
311         int lock_fd;
312
313         bool listening;
314 };
315
316 static void spoolss_next_client(void *pvt);
317
318 static int spoolss_children_main(struct tevent_context *ev_ctx,
319                                  struct pf_worker_data *pf,
320                                  int listen_fd, int lock_fd,
321                                  void *private_data)
322 {
323         struct messaging_context *msg_ctx = server_messaging_context();
324         struct spoolss_children_data *data;
325         bool ok;
326         int ret;
327
328         ok = spoolss_child_init(ev_ctx, pf);
329         if (!ok) {
330                 return 1;
331         }
332
333         data = talloc(ev_ctx, struct spoolss_children_data);
334         if (!data) {
335                 return 1;
336         }
337         data->pf = pf;
338         data->ev_ctx = ev_ctx;
339         data->msg_ctx = msg_ctx;
340         data->lock_fd = lock_fd;
341         data->listen_fd = listen_fd;
342         data->listening = false;
343
344         /* loop until it is time to exit */
345         while (pf->status != PF_WORKER_EXITING) {
346                 /* try to see if it is time to schedule the next client */
347                 spoolss_next_client(data);
348
349                 ret = tevent_loop_once(ev_ctx);
350                 if (ret != 0) {
351                         DEBUG(0, ("tevent_loop_once() exited with %d: %s\n",
352                                   ret, strerror(errno)));
353                         pf->status = PF_WORKER_EXITING;
354                 }
355         }
356
357         return ret;
358 }
359
360 static void spoolss_client_terminated(void *pvt)
361 {
362         struct spoolss_children_data *data;
363
364         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
365
366         if (data->pf->num_clients) {
367                 data->pf->num_clients--;
368         } else {
369                 DEBUG(2, ("Invalid num clients, aborting!\n"));
370                 data->pf->status = PF_WORKER_EXITING;
371                 return;
372         }
373
374         spoolss_next_client(pvt);
375 }
376
377 struct spoolss_new_client {
378         struct spoolss_children_data *data;
379         struct sockaddr_un sunaddr;
380         socklen_t addrlen;
381 };
382
383 static void spoolss_handle_client(struct tevent_req *req);
384
385 static void spoolss_next_client(void *pvt)
386 {
387         struct tevent_req *req;
388         struct spoolss_children_data *data;
389         struct spoolss_new_client *next;
390
391         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
392
393         if (data->pf->num_clients == 0) {
394                 data->pf->status = PF_WORKER_IDLE;
395         }
396
397         if (data->pf->cmds == PF_SRV_MSG_EXIT) {
398                 DEBUG(2, ("Parent process commands we terminate!\n"));
399                 return;
400         }
401
402         if (data->listening ||
403             data->pf->num_clients >= data->pf->allowed_clients) {
404                 /* nothing to do for now we are already listening
405                  * or reached the number of clients we are allowed
406                  * to handle in parallel */
407                 return;
408         }
409
410         next = talloc_zero(data, struct spoolss_new_client);
411         if (!next) {
412                 DEBUG(1, ("Out of memory!?\n"));
413                 return;
414         }
415         next->data = data;
416         next->addrlen = sizeof(next->sunaddr);
417
418         req = prefork_listen_send(next, data->ev_ctx, data->pf,
419                                   data->lock_fd, data->listen_fd,
420                                   (struct sockaddr *)&next->sunaddr,
421                                   &next->addrlen);
422         if (!req) {
423                 DEBUG(1, ("Failed to make listening request!?\n"));
424                 talloc_free(next);
425                 return;
426         }
427         tevent_req_set_callback(req, spoolss_handle_client, next);
428
429         data->listening = true;
430 }
431
432 static void spoolss_handle_client(struct tevent_req *req)
433 {
434         struct spoolss_children_data *data;
435         struct spoolss_new_client *client;
436         int ret;
437         int sd;
438
439         client = tevent_req_callback_data(req, struct spoolss_new_client);
440         data = client->data;
441
442         ret = prefork_listen_recv(req, &sd);
443
444         /* this will free the request too */
445         talloc_free(client);
446         /* we are done listening */
447         data->listening = false;
448
449         if (ret > 0) {
450                 DEBUG(1, ("Failed to accept client connection!\n"));
451                 /* bail out if we are not serving any other client */
452                 if (data->pf->num_clients == 0) {
453                         data->pf->status = PF_WORKER_EXITING;
454                 }
455                 return;
456         }
457
458         if (ret == -2) {
459                 DEBUG(1, ("Server asks us to die!\n"));
460                 data->pf->status = PF_WORKER_EXITING;
461                 return;
462         }
463
464         DEBUG(2, ("Spoolss preforked child %d got client connection!\n",
465                   (int)(data->pf->pid)));
466
467         named_pipe_accept_function(data->ev_ctx, data->msg_ctx,
468                                    SPOOLSS_PIPE_NAME, sd,
469                                    spoolss_client_terminated, data);
470 }
471
472 /* ==== Main Process Functions ==== */
473
474 static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx,
475                                       struct tevent_signal *se,
476                                       int signum, int count,
477                                       void *siginfo, void *pvt)
478 {
479         struct prefork_pool *pfp;
480         pid_t pid;
481         int status;
482         bool ok;
483         int active, total;
484         int n, r;
485
486         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
487
488         while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) {
489                 ok = prefork_mark_pid_dead(pfp, pid);
490                 if (!ok) {
491                         DEBUG(1, ("Pid %d was not found in children pool!\n",
492                                   (int)pid));
493                 }
494         }
495
496         /* now check we do not descent below the minimum */
497         active = prefork_count_active_children(pfp, &total);
498
499         n = 0;
500         if (total < spoolss_min_children) {
501                 n = total - spoolss_min_children;
502         } else if (total - active < (total / 4)) {
503                 n = spoolss_min_children;
504         }
505
506         if (n > 0) {
507                 r = prefork_add_children(ev_ctx, pfp, n);
508                 if (r < n) {
509                         DEBUG(10, ("Tried to start %d children but only,"
510                                    "%d were actually started.!\n", n, r));
511                 }
512         }
513
514
515 }
516
517 static bool spoolssd_setup_sig_chld_handler(struct tevent_context *ev_ctx,
518                                             struct prefork_pool *pfp)
519 {
520         struct tevent_signal *se;
521
522         se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
523                                 spoolssd_sig_chld_handler, pfp);
524         if (!se) {
525                 DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
526                 return false;
527         }
528
529         return true;
530 }
531
532 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
533                                     struct prefork_pool *pfp,
534                                     struct timeval current_time);
535 static void spoolssd_check_children(struct tevent_context *ev_ctx,
536                                     struct tevent_timer *te,
537                                     struct timeval current_time,
538                                     void *pvt);
539
540 static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
541                                             struct prefork_pool *pfp)
542 {
543         bool ok;
544
545         ok = spoolssd_setup_sig_chld_handler(ev_ctx, pfp);
546         if (!ok) {
547                 return false;
548         }
549
550         ok = spoolssd_schedule_check(ev_ctx, pfp, tevent_timeval_current());
551         return ok;
552 }
553
554 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
555                                     struct prefork_pool *pfp,
556                                     struct timeval current_time)
557 {
558         struct tevent_timer *te;
559         struct timeval next_event;
560
561         /* check situation again in 10 seconds */
562         next_event = tevent_timeval_current_ofs(10, 0);
563
564         /* check when the socket becomes readable, so that children
565          * are checked only when there is some activity */
566         te = tevent_add_timer(ev_ctx, pfp, next_event,
567                                 spoolssd_check_children, pfp);
568         if (!te) {
569                 DEBUG(2, ("Failed to set up children monitoring!\n"));
570                 return false;
571         }
572
573         return true;
574 }
575
576 static void spoolssd_check_children(struct tevent_context *ev_ctx,
577                                     struct tevent_timer *te,
578                                     struct timeval current_time,
579                                     void *pvt)
580 {
581         struct prefork_pool *pfp;
582         int active, total;
583         int ret, n;
584
585         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
586
587         active = prefork_count_active_children(pfp, &total);
588
589         if (total - active < spoolss_spawn_rate) {
590                 n = prefork_add_children(ev_ctx, pfp, spoolss_spawn_rate);
591                 if (n < spoolss_spawn_rate) {
592                         DEBUG(10, ("Tried to start 5 children but only,"
593                                    "%d were actually started.!\n", n));
594                 }
595         }
596
597         if (total - active > spoolss_min_children) {
598                 if ((total - spoolss_min_children) >= spoolss_spawn_rate) {
599                         prefork_retire_children(pfp, spoolss_spawn_rate,
600                                                 time(NULL) - SPOOLSS_MIN_LIFE);
601                 }
602         }
603
604         ret = spoolssd_schedule_check(ev_ctx, pfp, current_time);
605 }
606
607 void start_spoolssd(struct tevent_context *ev_ctx,
608                     struct messaging_context *msg_ctx)
609 {
610         struct prefork_pool *pool;
611         struct rpc_srv_callbacks spoolss_cb;
612         struct dcerpc_binding_vector *v;
613         TALLOC_CTX *mem_ctx;
614         pid_t pid;
615         NTSTATUS status;
616         int listen_fd;
617         int ret;
618         bool ok;
619
620         DEBUG(1, ("Forking SPOOLSS Daemon\n"));
621
622         pid = sys_fork();
623
624         if (pid == -1) {
625                 DEBUG(0, ("Failed to fork SPOOLSS [%s], aborting ...\n",
626                            strerror(errno)));
627                 exit(1);
628         }
629
630         if (pid) {
631                 /* parent */
632                 return;
633         }
634
635         /* child */
636         close_low_fds(false);
637
638         status = reinit_after_fork(msg_ctx,
639                                    ev_ctx,
640                                    procid_self(), true);
641         if (!NT_STATUS_IS_OK(status)) {
642                 DEBUG(0,("reinit_after_fork() failed\n"));
643                 smb_panic("reinit_after_fork() failed");
644         }
645
646         spoolss_reopen_logs();
647         spoolss_prefork_config();
648
649         /* the listening fd must be created before the children are actually
650          * forked out. */
651         listen_fd = create_named_pipe_socket(SPOOLSS_PIPE_NAME);
652         if (listen_fd == -1) {
653                 exit(1);
654         }
655
656         ret = listen(listen_fd, spoolss_max_children);
657         if (ret == -1) {
658                 DEBUG(0, ("Failed to listen on spoolss pipe - %s\n",
659                           strerror(errno)));
660                 exit(1);
661         }
662
663
664         /* start children before any more initialization is done */
665         ok = prefork_create_pool(ev_ctx, ev_ctx, listen_fd,
666                                  spoolss_min_children,
667                                  spoolss_max_children,
668                                  &spoolss_children_main, NULL,
669                                  &pool);
670
671         spoolss_setup_sig_term_handler(ev_ctx);
672         spoolss_setup_sig_hup_handler(ev_ctx, msg_ctx);
673
674         if (!serverid_register(procid_self(),
675                                 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
676                                 |FLAG_MSG_PRINT_GENERAL)) {
677                 exit(1);
678         }
679
680         if (!locking_init()) {
681                 exit(1);
682         }
683
684         messaging_register(msg_ctx, NULL,
685                            MSG_PRINTER_UPDATE, print_queue_receive);
686         messaging_register(msg_ctx, ev_ctx,
687                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
688
689         mem_ctx = talloc_new(NULL);
690         if (mem_ctx == NULL) {
691                 exit(1);
692         }
693
694         /*
695          * Initialize spoolss with an init function to convert printers first.
696          * static_init_rpc will try to initialize the spoolss server too but you
697          * can't register it twice.
698          */
699         spoolss_cb.init = spoolss_init_cb;
700         spoolss_cb.shutdown = spoolss_shutdown_cb;
701         spoolss_cb.private_data = msg_ctx;
702
703         status = rpc_winreg_init(NULL);
704         if (!NT_STATUS_IS_OK(status)) {
705                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
706                           nt_errstr(status)));
707                 exit(1);
708         }
709
710         status = rpc_spoolss_init(&spoolss_cb);
711         if (!NT_STATUS_IS_OK(status)) {
712                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
713                           nt_errstr(status)));
714                 exit(1);
715         }
716
717         status = dcerpc_binding_vector_new(mem_ctx, &v);
718         if (!NT_STATUS_IS_OK(status)) {
719                 DEBUG(0, ("Failed to create binding vector (%s)\n",
720                           nt_errstr(status)));
721                 exit(1);
722         }
723
724         status = dcerpc_binding_vector_add_np_default(&ndr_table_spoolss, v);
725         if (!NT_STATUS_IS_OK(status)) {
726                 DEBUG(0, ("Failed to add np to binding vector (%s)\n",
727                           nt_errstr(status)));
728                 exit(1);
729         }
730
731         status = rpc_ep_register(ev_ctx, msg_ctx, &ndr_table_spoolss, v);
732         if (!NT_STATUS_IS_OK(status)) {
733                 DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
734                           nt_errstr(status)));
735                 exit(1);
736         }
737
738         talloc_free(mem_ctx);
739
740         ok = spoolssd_setup_children_monitor(ev_ctx, pool);
741         if (!ok) {
742                 DEBUG(0, ("Failed to setup children monitoring!\n"));
743                 exit(1);
744         }
745
746         reload_printers(ev_ctx, msg_ctx);
747
748         DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));
749
750         /* loop forever */
751         ret = tevent_loop_wait(ev_ctx);
752
753         /* should not be reached */
754         DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
755                  ret, (ret == 0) ? "out of events" : strerror(errno)));
756         exit(1);
757 }