a241e24798e6bb8beaab2e34684486781523f698
[ddiss/samba.git] / source3 / lib / server_prefork.c
1 /*
2    Unix SMB/CIFS implementation.
3    Common server globals
4
5    Copyright (C) Simo Sorce <idra@samba.org> 2011
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "serverid.h"
23 #include "messages.h"
24 #include "system/time.h"
25 #include "system/shmem.h"
26 #include "system/filesys.h"
27 #include "server_prefork.h"
28 #include "../lib/util/util.h"
29 #include "../lib/util/tevent_unix.h"
30
31 struct prefork_pool {
32
33         int listen_fd_size;
34         int *listen_fds;
35
36         prefork_main_fn_t *main_fn;
37         void *private_data;
38
39         int pool_size;
40         struct pf_worker_data *pool;
41
42         int allowed_clients;
43
44         prefork_sigchld_fn_t *sigchld_fn;
45         void *sigchld_data;
46 };
47
48 static bool prefork_setup_sigchld_handler(struct tevent_context *ev_ctx,
49                                             struct prefork_pool *pfp);
50
51 static int prefork_pool_destructor(struct prefork_pool *pfp)
52 {
53         anonymous_shared_free(pfp->pool);
54         return 0;
55 }
56
57 bool prefork_create_pool(TALLOC_CTX *mem_ctx,
58                          struct tevent_context *ev_ctx,
59                          struct messaging_context *msg_ctx,
60                          int listen_fd_size, int *listen_fds,
61                          int min_children, int max_children,
62                          prefork_main_fn_t *main_fn, void *private_data,
63                          struct prefork_pool **pf_pool)
64 {
65         struct prefork_pool *pfp;
66         pid_t pid;
67         time_t now = time(NULL);
68         size_t data_size;
69         int ret;
70         int i;
71         bool ok;
72
73         pfp = talloc_zero(mem_ctx, struct prefork_pool);
74         if (!pfp) {
75                 DEBUG(1, ("Out of memory!\n"));
76                 return false;
77         }
78         pfp->listen_fd_size = listen_fd_size;
79         pfp->listen_fds = talloc_array(pfp, int, listen_fd_size);
80         if (!pfp->listen_fds) {
81                 DEBUG(1, ("Out of memory!\n"));
82                 return false;
83         }
84         for (i = 0; i < listen_fd_size; i++) {
85                 pfp->listen_fds[i] = listen_fds[i];
86                 /* force sockets in non-blocking mode */
87                 set_blocking(listen_fds[i], false);
88         }
89         pfp->main_fn = main_fn;
90         pfp->private_data = private_data;
91
92         pfp->pool_size = max_children;
93         data_size = sizeof(struct pf_worker_data) * max_children;
94
95         pfp->pool = anonymous_shared_allocate(data_size);
96         if (pfp->pool == NULL) {
97                 DEBUG(1, ("Failed to mmap memory for prefork pool!\n"));
98                 talloc_free(pfp);
99                 return false;
100         }
101         talloc_set_destructor(pfp, prefork_pool_destructor);
102
103         for (i = 0; i < min_children; i++) {
104
105                 pfp->pool[i].allowed_clients = 1;
106                 pfp->pool[i].started = now;
107
108                 pid = sys_fork();
109                 switch (pid) {
110                 case -1:
111                         DEBUG(1, ("Failed to prefork child n. %d !\n", i));
112                         break;
113
114                 case 0: /* THE CHILD */
115
116                         pfp->pool[i].status = PF_WORKER_ALIVE;
117                         ret = pfp->main_fn(ev_ctx, msg_ctx,
118                                            &pfp->pool[i], i + 1,
119                                            pfp->listen_fd_size,
120                                            pfp->listen_fds,
121                                            pfp->private_data);
122                         exit(ret);
123
124                 default: /* THE PARENT */
125                         pfp->pool[i].pid = pid;
126                         break;
127                 }
128         }
129
130         ok = prefork_setup_sigchld_handler(ev_ctx, pfp);
131         if (!ok) {
132                 DEBUG(1, ("Failed to setup SIGCHLD Handler!\n"));
133                 talloc_free(pfp);
134                 return false;
135         }
136
137         *pf_pool = pfp;
138         return true;
139 }
140
141 /* Provide the new max children number in new_max
142  * (must be larger than current max).
143  * Returns: 0 if all fine
144  *          ENOSPC if mremap fails to expand
145  *          EINVAL if new_max is invalid
146  */
147 int prefork_expand_pool(struct prefork_pool *pfp, int new_max)
148 {
149         struct prefork_pool *pool;
150         size_t old_size;
151         size_t new_size;
152         int ret;
153
154         if (new_max <= pfp->pool_size) {
155                 return EINVAL;
156         }
157
158         old_size = sizeof(struct pf_worker_data) * pfp->pool_size;
159         new_size = sizeof(struct pf_worker_data) * new_max;
160
161         pool = anonymous_shared_resize(&pfp->pool, new_size, false);
162         if (pool == NULL) {
163                 ret = errno;
164                 DEBUG(3, ("Failed to mremap memory (%d: %s)!\n",
165                           ret, strerror(ret)));
166                 return ret;
167         }
168
169         memset(&pool[pfp->pool_size], 0, new_size - old_size);
170
171         pfp->pool_size = new_max;
172
173         return 0;
174 }
175
176 int prefork_add_children(struct tevent_context *ev_ctx,
177                          struct messaging_context *msg_ctx,
178                          struct prefork_pool *pfp,
179                          int num_children)
180 {
181         pid_t pid;
182         time_t now = time(NULL);
183         int ret;
184         int i, j;
185
186         for (i = 0, j = 0; i < pfp->pool_size && j < num_children; i++) {
187
188                 if (pfp->pool[i].status != PF_WORKER_NONE) {
189                         continue;
190                 }
191
192                 pfp->pool[i].allowed_clients = 1;
193                 pfp->pool[i].started = now;
194
195                 pid = sys_fork();
196                 switch (pid) {
197                 case -1:
198                         DEBUG(1, ("Failed to prefork child n. %d !\n", j));
199                         break;
200
201                 case 0: /* THE CHILD */
202
203                         pfp->pool[i].status = PF_WORKER_ALIVE;
204                         ret = pfp->main_fn(ev_ctx, msg_ctx,
205                                            &pfp->pool[i], i + 1,
206                                            pfp->listen_fd_size,
207                                            pfp->listen_fds,
208                                            pfp->private_data);
209
210                         pfp->pool[i].status = PF_WORKER_EXITING;
211                         exit(ret);
212
213                 default: /* THE PARENT */
214                         pfp->pool[i].pid = pid;
215                         j++;
216                         break;
217                 }
218         }
219
220         DEBUG(5, ("Added %d children!\n", j));
221
222         return j;
223 }
224
225 struct prefork_oldest {
226         int num;
227         time_t started;
228 };
229
230 /* sort in inverse order */
231 static int prefork_sort_oldest(const void *ap, const void *bp)
232 {
233         const struct prefork_oldest *a = (const struct prefork_oldest *)ap;
234         const struct prefork_oldest *b = (const struct prefork_oldest *)bp;
235
236         if (a->started == b->started) {
237                 return 0;
238         }
239         if (a->started < b->started) {
240                 return 1;
241         }
242         return -1;
243 }
244
245 int prefork_retire_children(struct messaging_context *msg_ctx,
246                             struct prefork_pool *pfp,
247                             int num_children, time_t age_limit)
248 {
249         const DATA_BLOB ping = data_blob_null;
250         time_t now = time(NULL);
251         struct prefork_oldest *oldest;
252         int i, j;
253
254         oldest = talloc_array(pfp, struct prefork_oldest, pfp->pool_size);
255         if (!oldest) {
256                 return -1;
257         }
258
259         for (i = 0; i < pfp->pool_size; i++) {
260                 oldest[i].num = i;
261                 if (pfp->pool[i].status == PF_WORKER_ALIVE ||
262                     pfp->pool[i].status == PF_WORKER_ACCEPTING) {
263                         oldest[i].started = pfp->pool[i].started;
264                 } else {
265                         oldest[i].started = now;
266                 }
267         }
268
269         qsort(oldest, pfp->pool_size,
270                 sizeof(struct prefork_oldest),
271                 prefork_sort_oldest);
272
273         for (i = 0, j = 0; i < pfp->pool_size && j < num_children; i++) {
274                 if (((pfp->pool[i].status == PF_WORKER_ALIVE) &&
275                      (pfp->pool[i].num_clients < 1)) &&
276                     (pfp->pool[i].started <= age_limit)) {
277                         /* tell the child it's time to give up */
278                         DEBUG(5, ("Retiring pid %d!\n", pfp->pool[i].pid));
279                         pfp->pool[i].cmds = PF_SRV_MSG_EXIT;
280                         messaging_send(msg_ctx,
281                                         pid_to_procid(pfp->pool[i].pid),
282                                         MSG_PREFORK_PARENT_EVENT, &ping);
283                         j++;
284                 }
285         }
286
287         return j;
288 }
289
290 int prefork_count_children(struct prefork_pool *pfp, int *active)
291 {
292         int i, a, t;
293
294         a = 0;
295         t = 0;
296         for (i = 0; i < pfp->pool_size; i++) {
297                 if (pfp->pool[i].status == PF_WORKER_NONE) {
298                         continue;
299                 }
300
301                 t++;
302
303                 if ((pfp->pool[i].status == PF_WORKER_EXITING) ||
304                     (pfp->pool[i].num_clients <= 0)) {
305                         continue;
306                 }
307
308                 a++;
309         }
310
311         if (active) {
312                 *active = a;
313         }
314         return t;
315 }
316
317 static void prefork_cleanup_loop(struct prefork_pool *pfp)
318 {
319         int status;
320         pid_t pid;
321         int i;
322
323         /* TODO: should we use a process group id wait instead of looping ? */
324         for (i = 0; i < pfp->pool_size; i++) {
325                 if (pfp->pool[i].status == PF_WORKER_NONE ||
326                     pfp->pool[i].pid == 0) {
327                         continue;
328                 }
329
330                 pid = sys_waitpid(pfp->pool[i].pid, &status, WNOHANG);
331                 if (pid > 0) {
332
333                         if (pfp->pool[i].status != PF_WORKER_EXITING) {
334                                 DEBUG(3, ("Child (%d) terminated abnormally:"
335                                           " %d\n", (int)pid, status));
336                         } else {
337                                 DEBUG(10, ("Child (%d) terminated with status:"
338                                            " %d\n", (int)pid, status));
339                         }
340
341                         /* reset all fields,
342                          * this makes status = PF_WORK_NONE */
343                         memset(&pfp->pool[i], 0,
344                                 sizeof(struct pf_worker_data));
345                 }
346         }
347
348 }
349
350 int prefork_count_allowed_connections(struct prefork_pool *pfp)
351 {
352         int c;
353         int i;
354
355         c = 0;
356         for (i = 0; i < pfp->pool_size; i++) {
357                 if (pfp->pool[i].status == PF_WORKER_NONE ||
358                     pfp->pool[i].status == PF_WORKER_EXITING) {
359                         continue;
360                 }
361
362                 if (pfp->pool[i].num_clients < 0) {
363                         continue;
364                 }
365
366                 c += pfp->pool[i].allowed_clients - pfp->pool[i].num_clients;
367         }
368
369         return c;
370 }
371
372 void prefork_increase_allowed_clients(struct prefork_pool *pfp, int max)
373 {
374         int i;
375
376         for (i = 0; i < pfp->pool_size; i++) {
377                 if (pfp->pool[i].status == PF_WORKER_NONE ||
378                     pfp->pool[i].status == PF_WORKER_EXITING) {
379                         continue;
380                 }
381
382                 if (pfp->pool[i].num_clients < 0) {
383                         continue;
384                 }
385
386                 if (pfp->pool[i].allowed_clients < max) {
387                         pfp->pool[i].allowed_clients++;
388                 }
389         }
390 }
391
392 void prefork_decrease_allowed_clients(struct prefork_pool *pfp)
393 {
394         int i;
395
396         for (i = 0; i < pfp->pool_size; i++) {
397                 if (pfp->pool[i].status == PF_WORKER_NONE ||
398                     pfp->pool[i].status == PF_WORKER_EXITING) {
399                         continue;
400                 }
401
402                 if (pfp->pool[i].num_clients < 0) {
403                         continue;
404                 }
405
406                 if (pfp->pool[i].allowed_clients > 1) {
407                         pfp->pool[i].allowed_clients--;
408                 }
409         }
410 }
411
412 void prefork_reset_allowed_clients(struct prefork_pool *pfp)
413 {
414         int i;
415
416         for (i = 0; i < pfp->pool_size; i++) {
417                 pfp->pool[i].allowed_clients = 1;
418         }
419 }
420
421 void prefork_send_signal_to_all(struct prefork_pool *pfp, int signal_num)
422 {
423         int i;
424
425         for (i = 0; i < pfp->pool_size; i++) {
426                 if (pfp->pool[i].status == PF_WORKER_NONE) {
427                         continue;
428                 }
429
430                 kill(pfp->pool[i].pid, signal_num);
431         }
432 }
433
434 void prefork_warn_active_children(struct messaging_context *msg_ctx,
435                                   struct prefork_pool *pfp)
436 {
437         const DATA_BLOB ping = data_blob_null;
438         int i;
439
440         for (i = 0; i < pfp->pool_size; i++) {
441                 if (pfp->pool[i].status == PF_WORKER_NONE) {
442                         continue;
443                 }
444
445                 messaging_send(msg_ctx,
446                                 pid_to_procid(pfp->pool[i].pid),
447                                 MSG_PREFORK_PARENT_EVENT, &ping);
448         }
449 }
450
451 static void prefork_sigchld_handler(struct tevent_context *ev_ctx,
452                                     struct tevent_signal *se,
453                                     int signum, int count,
454                                     void *siginfo, void *pvt)
455 {
456         struct prefork_pool *pfp;
457
458         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
459
460         /* run the cleanup function to make sure all dead children are
461          * properly and timely retired. */
462         prefork_cleanup_loop(pfp);
463
464         if (pfp->sigchld_fn) {
465                 pfp->sigchld_fn(ev_ctx, pfp, pfp->sigchld_data);
466         }
467 }
468
469 static bool prefork_setup_sigchld_handler(struct tevent_context *ev_ctx,
470                                           struct prefork_pool *pfp)
471 {
472         struct tevent_signal *se;
473
474         se = tevent_add_signal(ev_ctx, pfp, SIGCHLD, 0,
475                                 prefork_sigchld_handler, pfp);
476         if (!se) {
477                 DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
478                 return false;
479         }
480
481         return true;
482 }
483
484 void prefork_set_sigchld_callback(struct prefork_pool *pfp,
485                                   prefork_sigchld_fn_t *sigchld_fn,
486                                   void *private_data)
487 {
488         pfp->sigchld_fn = sigchld_fn;
489         pfp->sigchld_data = private_data;
490 }
491
492 /* ==== Functions used by children ==== */
493
494 struct pf_listen_state {
495         struct tevent_context *ev;
496         struct pf_worker_data *pf;
497
498         int listen_fd_size;
499         int *listen_fds;
500
501         int accept_fd;
502
503         struct tsocket_address *srv_addr;
504         struct tsocket_address *cli_addr;
505
506         int error;
507 };
508
509 struct pf_listen_ctx {
510         TALLOC_CTX *fde_ctx;
511         struct tevent_req *req;
512         int listen_fd;
513 };
514
515 static void prefork_listen_accept_handler(struct tevent_context *ev,
516                                           struct tevent_fd *fde,
517                                           uint16_t flags, void *pvt);
518
519 struct tevent_req *prefork_listen_send(TALLOC_CTX *mem_ctx,
520                                         struct tevent_context *ev,
521                                         struct pf_worker_data *pf,
522                                         int listen_fd_size,
523                                         int *listen_fds)
524 {
525         struct tevent_req *req;
526         struct pf_listen_state *state;
527         struct pf_listen_ctx *ctx;
528         struct tevent_fd *fde;
529         TALLOC_CTX *fde_ctx;
530         int i;
531
532         req = tevent_req_create(mem_ctx, &state, struct pf_listen_state);
533         if (!req) {
534                 return NULL;
535         }
536
537         state->ev = ev;
538         state->pf = pf;
539         state->listen_fd_size = listen_fd_size;
540         state->listen_fds = listen_fds;
541         state->accept_fd = -1;
542         state->error = 0;
543
544         fde_ctx = talloc_new(state);
545         if (tevent_req_nomem(fde_ctx, req)) {
546                 return tevent_req_post(req, ev);
547         }
548
549         /* race on accept */
550         for (i = 0; i < state->listen_fd_size; i++) {
551                 ctx = talloc(fde_ctx, struct pf_listen_ctx);
552                 if (tevent_req_nomem(ctx, req)) {
553                         return tevent_req_post(req, ev);
554                 }
555                 ctx->fde_ctx = fde_ctx;
556                 ctx->req = req;
557                 ctx->listen_fd = state->listen_fds[i];
558
559                 fde = tevent_add_fd(state->ev, fde_ctx,
560                                     ctx->listen_fd, TEVENT_FD_READ,
561                                     prefork_listen_accept_handler, ctx);
562                 if (tevent_req_nomem(fde, req)) {
563                         return tevent_req_post(req, ev);
564                 }
565         }
566
567         pf->status = PF_WORKER_ACCEPTING;
568
569         return req;
570 }
571
572 static void prefork_listen_accept_handler(struct tevent_context *ev,
573                                           struct tevent_fd *fde,
574                                           uint16_t flags, void *pvt)
575 {
576         struct pf_listen_state *state;
577         struct tevent_req *req;
578         struct pf_listen_ctx *ctx;
579         struct sockaddr_storage addr;
580         socklen_t addrlen;
581         int soerr = 0;
582         socklen_t solen = sizeof(soerr);
583         int sd = -1;
584         int ret;
585
586         ctx = talloc_get_type_abort(pvt, struct pf_listen_ctx);
587         req = ctx->req;
588         state = tevent_req_data(ctx->req, struct pf_listen_state);
589
590         if ((state->pf->cmds == PF_SRV_MSG_EXIT) &&
591             (state->pf->num_clients <= 0)) {
592                 /* We have been asked to exit, so drop here and the next
593                  * child will pick it up */
594                 state->pf->status = PF_WORKER_EXITING;
595                 state->error = EINTR;
596                 goto done;
597         }
598
599         /* before proceeding check that the listening fd is ok */
600         ret = getsockopt(ctx->listen_fd, SOL_SOCKET, SO_ERROR, &soerr, &solen);
601         if (ret == -1) {
602                 /* this is a fatal error, we cannot continue listening */
603                 state->error = EBADF;
604                 goto done;
605         }
606         if (soerr != 0) {
607                 /* this is a fatal error, we cannot continue listening */
608                 state->error = soerr;
609                 goto done;
610         }
611
612         ZERO_STRUCT(addr);
613         addrlen = sizeof(addr);
614         sd = accept(ctx->listen_fd, (struct sockaddr *)&addr, &addrlen);
615         if (sd == -1) {
616                 state->error = errno;
617                 DEBUG(6, ("Accept failed! (%d, %s)\n",
618                           state->error, strerror(state->error)));
619                 goto done;
620         }
621
622         state->accept_fd = sd;
623
624         ret = tsocket_address_bsd_from_sockaddr(state,
625                                         (struct sockaddr *)(void *)&addr,
626                                         addrlen, &state->cli_addr);
627         if (ret < 0) {
628                 state->error = errno;
629                 goto done;
630         }
631
632         ZERO_STRUCT(addr);
633         addrlen = sizeof(addr);
634         ret = getsockname(sd, (struct sockaddr *)(void *)&addr, &addrlen);
635         if (ret < 0) {
636                 state->error = errno;
637                 goto done;
638         }
639
640         ret = tsocket_address_bsd_from_sockaddr(state,
641                                         (struct sockaddr *)(void *)&addr,
642                                         addrlen, &state->srv_addr);
643         if (ret < 0) {
644                 state->error = errno;
645                 goto done;
646         }
647
648 done:
649         /* do not track the listen fds anymore */
650         talloc_free(ctx->fde_ctx);
651         tevent_req_done(req);
652 }
653
654 int prefork_listen_recv(struct tevent_req *req,
655                         TALLOC_CTX *mem_ctx, int *fd,
656                         struct tsocket_address **srv_addr,
657                         struct tsocket_address **cli_addr)
658 {
659         struct pf_listen_state *state;
660         int ret = 0;
661
662         state = tevent_req_data(req, struct pf_listen_state);
663
664         if (state->error) {
665                 ret = state->error;
666         } else {
667                 tevent_req_is_unix_error(req, &ret);
668         }
669
670         if (ret) {
671                 if (state->accept_fd != -1) {
672                         close(state->accept_fd);
673                 }
674         } else {
675                 *fd = state->accept_fd;
676                 *srv_addr = talloc_move(mem_ctx, &state->srv_addr);
677                 *cli_addr = talloc_move(mem_ctx, &state->cli_addr);
678                 state->pf->num_clients++;
679         }
680         if (state->pf->status == PF_WORKER_ACCEPTING) {
681                 state->pf->status = PF_WORKER_ALIVE;
682         }
683
684         tevent_req_received(req);
685         return ret;
686 }