[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: cannot kill slapd from openldap-1.2.11

On Tue, 18 Jul 2000, Terry Lambert wrote:

> [ ... ]
> The problem is system call restart on the select, following
> the select being interrupted by a caught signal.

Just a question:  Should catching a signal cause select
to return error EINTR according to BSD standard?

On linux with glibc2 which tries to follow BSD standard
with respect to the signal() semantics, the read() and
write() will be automatically restarted, whereas select()
will return with error EINTR after a signal handler has

On linux with the older libc5 the signal() follows sysv
semantics, and as a result of that a few programs which
relied in sysv signals no longer reacted on signals.

> One could argue that OpenLDAP should be written to be more
> platform independant.  In particular, if there were set up
> a setjmp in the main loop, and the signal handler set the
> flag and did a longjmp, instead of merely setting the flag
> and depending on non-restart behaviour, this signal handling
> would be portable to about 140 platforms on which I've done
> similar code.  As it is, about 60 of those platforms will
> exhibit the behaviour you are seeing, and on those platforms,
> the behaviour (system call restart following signal trap) is
> _correct_ behaviour.

If it isn't then you could get strange, hard to debug,
errors which seams to happen at random.  Also bear in mind
that if system calls are not automaticaly restarted then the
program should do that anytime a system call returns EINTR
and the situation does not call for an abort at this point.

If the signal handler longjmps (must be siglongjmp where
available) back to the main loop then you need not worry
about restarting anything.

> 2.2.8 libc_r was brought into strict POSIX threads Draft 4
> conformance by Jeremy Allison and myself, in particular for
> support of LDAP and ACAP (we also had to patch the STL, which
> was not Draft 4 capable, and the Cyrus ACAP server, as well
> as the exception handing in g++ 2.95).
> FreeBSD 4.x is striving for POSIX standard (non-draft)
> conformance, and Jason Evans is doing the work; one might
> argue that full conformance with the Draft 4 is better
> than partial conformance with the standard.  8-(.  At
> least with Draft 4, you know that everything that works
> on IRIX and a common release of Tru64 will work on FreeBSD
> (2.2.6+).

In short, does the POSIX draft now specify the semantics
for signals(), and is that going to be sysv or BSD or
something in between?  And X-OPEN?

The "Advanced Programming in a Unix Environment" by
Stewens spend quite a few pages in this signal issue and
the pitfalls this contains.

> PS: I reported this bug to Jason Evans, but have not seen
> whether or not it was fixed.
> PPS: Another way of dealing with this would be for OpenLDAP
> to use the POSIX interfaces, rather than the old signal
> interfaces.  This would allow the specification of the
> sa_flags=0 to defeat restart in all cases, making the code
> more determanistic, and less likely to vary in behaviour
> from platform to platform.
> Let me know if anyone needs help or advice making these
> changes; as it is, I am rather swamped for at least the
> next 3 weeks...

The following litle program can be used to test the signal
behaviour with respect to read() and select() restarts.

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>


static void (*my_signal(int sig, void (*handler) (int))) (int) {
    struct sigaction sa, osa;
    sa.sa_handler = handler;
    sa.sa_flags = 0;
    sa.sa_restorer = NULL;
    if (sigaction(sig, &sa, &osa) == -1) {
        return SIG_ERR;
    } else {
        return osa.sa_handler;
#define signal my_signal


static void catcher(int sig)
    printf("Caught signal %d\n", sig);

static void Quit(int sig)
    printf("Caught signal %d\n", sig);

static void Die(char *msg)

int main()
    int cc;
    char buf[64];
    fd_set rfds;

    if (signal(SIGINT, catcher) == SIG_ERR)
        Die("Signal error");
    if (signal(SIGQUIT, Quit) == SIG_ERR)
        Die("Signal error");

    while (1) {
        FD_SET(0, &rfds);
        cc = select(1, &rfds, NULL, NULL, NULL);

        if (cc == -1) {
            printf("Select returned error %d\n", errno);
        } else {
            printf("Select returned %d\n", cc);

        cc = read(0, buf, sizeof buf);
        if (cc == -1) {
            printf("Read returned error %d\n", errno);
        } else {
            printf("Read returned %d\n", cc);