~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to src/master/service-monitor.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "common.h"
4
4
#include "array.h"
24
24
#define SERVICE_DROP_TIMEOUT_MSECS (10*1000)
25
25
#define MAX_DIE_WAIT_SECS 5
26
26
#define SERVICE_MAX_EXIT_FAILURES_IN_SEC 10
 
27
#define SERVICE_PREFORK_MAX_AT_ONCE 10
27
28
 
28
29
static void service_monitor_start_extra_avail(struct service *service);
29
30
static void service_status_more(struct service_process *process,
81
82
            service->process_count == service->process_limit)
82
83
                service_login_notify(service, TRUE);
83
84
 
84
 
        /* we may need to start more  */
 
85
        /* we may need to start more */
85
86
        service_monitor_start_extra_avail(service);
86
87
        service_monitor_listen_start(service);
87
88
}
101
102
                process->idle_start = ioloop_time;
102
103
                if (service->process_avail > service->set->process_min_avail &&
103
104
                    process->to_idle == NULL &&
104
 
                    service->idle_kill != -1U) {
 
105
                    service->idle_kill != UINT_MAX) {
105
106
                        /* we have more processes than we really need.
106
107
                           add a bit of randomness so that we don't send the
107
108
                           signal to all of them at once */
122
123
{
123
124
        struct service_process *process;
124
125
 
125
 
        process = hash_table_lookup(service_pids, &status->pid);
 
126
        process = hash_table_lookup(service_pids, POINTER_CAST(status->pid));
126
127
        if (process == NULL) {
127
128
                /* we've probably wait()ed it away already. ignore */
128
129
                return;
237
238
static void service_drop_connections(struct service_listener *l)
238
239
{
239
240
        struct service *service = l->service;
 
241
        const char *limit_name;
240
242
        unsigned int limit;
241
243
        int fd;
242
244
 
243
245
        if (service->last_drop_warning +
244
246
            SERVICE_DROP_WARN_INTERVAL_SECS < ioloop_time) {
245
247
                service->last_drop_warning = ioloop_time;
246
 
                limit = service->process_limit > 1 ?
247
 
                        service->process_limit : service->client_limit;
 
248
                if (service->process_limit > 1) {
 
249
                        limit_name = "process_limit";
 
250
                        limit = service->process_limit;
 
251
                } else if (service->set->service_count == 1) {
 
252
                        i_assert(service->client_limit == 1);
 
253
                        limit_name = "client_limit/service_count";
 
254
                        limit = 1;
 
255
                } else {
 
256
                        limit_name = "client_limit";
 
257
                        limit = service->client_limit;
 
258
                }
248
259
                i_warning("service(%s): %s (%u) reached, "
249
260
                          "client connections are being dropped",
250
 
                          service->set->name,
251
 
                          service->process_limit > 1 ?
252
 
                          "process_limit" : "client_limit", limit);
 
261
                          service->set->name, limit_name, limit);
253
262
        }
254
263
 
255
264
        if (service->type == SERVICE_TYPE_LOGIN) {
294
303
                service_monitor_listen_stop(service);
295
304
}
296
305
 
297
 
static void service_monitor_start_extra_avail(struct service *service)
 
306
static bool
 
307
service_monitor_start_count(struct service *service, unsigned int limit)
298
308
{
299
309
        unsigned int i, count;
300
310
 
301
 
        if (service->process_avail >= service->set->process_min_avail ||
302
 
            service->list->destroying)
303
 
                return;
 
311
        i_assert(service->set->process_min_avail >= service->process_avail);
304
312
 
305
313
        count = service->set->process_min_avail - service->process_avail;
306
314
        if (service->process_count + count > service->process_limit)
307
315
                count = service->process_limit - service->process_count;
 
316
        if (count > limit)
 
317
                count = limit;
308
318
 
309
319
        for (i = 0; i < count; i++) {
310
320
                if (service_process_create(service) == NULL) {
316
326
                /* we created some processes, they'll do the listening now */
317
327
                service_monitor_listen_stop(service);
318
328
        }
 
329
        return i == count;
 
330
}
 
331
 
 
332
static void service_monitor_prefork_timeout(struct service *service)
 
333
{
 
334
        /* don't prefork more processes if other more important processes had
 
335
           been forked while we were waiting for this timeout (= master seems
 
336
           busy) */
 
337
        if (service->list->fork_counter != service->prefork_counter) {
 
338
                service->prefork_counter = service->list->fork_counter;
 
339
                return;
 
340
        }
 
341
        if (service->process_avail < service->set->process_min_avail) {
 
342
                if (service_monitor_start_count(service, SERVICE_PREFORK_MAX_AT_ONCE) &&
 
343
                    service->process_avail < service->set->process_min_avail)
 
344
                        return;
 
345
        }
 
346
        timeout_remove(&service->to_prefork);
 
347
}
 
348
 
 
349
static void service_monitor_start_extra_avail(struct service *service)
 
350
{
 
351
        if (service->process_avail >= service->set->process_min_avail ||
 
352
            service->list->destroying)
 
353
                return;
 
354
 
 
355
        if (service->process_avail == 0) {
 
356
                /* quickly start one process now */
 
357
                if (!service_monitor_start_count(service, 1))
 
358
                        return;
 
359
                if (service->process_avail >= service->set->process_min_avail)
 
360
                        return;
 
361
        }
 
362
        if (service->to_prefork == NULL) {
 
363
                /* ioloop handles timeouts before fds (= SIGCHLD callback),
 
364
                   so let the first timeout handler call simply update the fork
 
365
                   counter and the second one check if we're busy or not. */
 
366
                service->to_prefork =
 
367
                        timeout_add_short(0, service_monitor_prefork_timeout, service);
 
368
        }
319
369
}
320
370
 
321
371
static void service_monitor_listen_start_force(struct service *service)
363
413
 
364
414
static int service_login_create_notify_fd(struct service *service)
365
415
{
366
 
        int fd;
 
416
        int fd, ret;
367
417
 
368
418
        if (service->login_notify_fd != -1)
369
419
                return 0;
389
439
                }
390
440
        } T_END;
391
441
 
 
442
        ret = fd == -1 ? -1 : 0;
392
443
        if (fd != service->login_notify_fd)
393
 
                (void)close(fd);
394
 
        return fd == -1 ? -1 : 0;
 
444
                i_close_fd(&fd);
 
445
        return ret;
395
446
}
396
447
 
397
448
void services_monitor_start(struct service_list *service_list)
482
533
 
483
534
        if (service->to_throttle != NULL)
484
535
                timeout_remove(&service->to_throttle);
 
536
        if (service->to_prefork != NULL)
 
537
                timeout_remove(&service->to_prefork);
485
538
}
486
539
 
487
540
static void services_monitor_wait(struct service_list *service_list)
565
618
        bool service_stopped, throttle;
566
619
 
567
620
        while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
568
 
                process = hash_table_lookup(service_pids, &pid);
 
621
                process = hash_table_lookup(service_pids, POINTER_CAST(pid));
569
622
                if (process == NULL) {
570
623
                        i_error("waitpid() returned unknown PID %s",
571
624
                                dec2str(pid));
601
654
                service_stopped = service->status_fd[0] == -1;
602
655
                if (!service_stopped) {
603
656
                        service_monitor_start_extra_avail(service);
 
657
                        /* if there are no longer listening processes,
 
658
                           start listening for more */
604
659
                        if (service->to_throttle == NULL)
605
660
                                service_monitor_listen_start(service);
606
661
                }