Wietse Venema:
> > How do I fix the system's ZERO-DELAY timer?
> 
> I can write a small test program. If it reproduces the problem,
> then there are two things that need to be done.
> 
> 1) The program needs to be sent to VMware as part of a bug report.
> 
> 2) We can try to program around this bug until the vendor fixes
> it.  Perhaps some system configuration will suffice. For example,
> many virtualization systems emulate a number of "hardware" timers
> such as ACPI, TSC etc.  and some emulations may be less buggy.
> 
> But first, you need to get some recent Postfix source code on the
> machine so that we can do some quick tests.  There is no need to
> overwrite the installed Postfix.

Attached is a small test program, to be run in the virtual machine. 

Please save as postfix-x.x-yyyymmdd/src/util/zero_delay.c where
postfix-x.x-yyyymmdd is the top-level directory from a recent
Postfix release (2.4 or later).

Then,

    cd postfix-x.x-yyyymmdd
    make
    (get some coffee)
    cd src/util
    make zero_delay | sed 's/$/ libutil/a' | sh

The result is a test program zero_delay, to be run as:

    ./zero_delay

It should run for 10-20 seconds or so then terminate with

    normal completion after 1000000 iterations

If instead it terminates with

    timer event lost after N iterations

then you have found the timer bug that causes Postfix to deliver
only one message probe per 300 seconds, and we can start looking
for workarounds (such as changing the src/util/events.c module and
replacing zero delay requests by 1 millisecond delay requests).

        Wietse
#include <sys_defs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <events.h>

#define HOWMANY 1000000

typedef struct {
        int count;
} LOOP_COUNT;

static LOOP_COUNT loop_count;

static void alarm_event(int sig)
{
    printf("timer event lost after %d iterations\n", loop_count.count);
    exit(1);
}

static void timer_event(int event_type, char *context)
{
    LOOP_COUNT *lc = (LOOP_COUNT *) context;

    lc->count += 1;
    if (lc->count >= HOWMANY) {
        printf("normal completion after %d iterations\n", lc->count);
        exit(0);
    } else {
        alarm(2);
        event_request_timer(timer_event, (char *) lc, 0);
    }
}

int     main(int argc, char **argv)
{

    signal(SIGALRM, alarm_event);
    alarm(2);
    event_request_timer(timer_event, (char *) &loop_count, 0);
    event_drain(HOWMANY);
}

Reply via email to