1
1
openmpi/opal/event/signal.c
Brian Barrett 11932e89d5 Fix nasty bug Josh was seeing where cntl-c wasn't working when orterun hangs up
in finalize after the first cntl-c is sent.

If the signal delete function was called while the signal set was blocked (which
is really most of the time in OMPI), the signal handler would be set to default
and the event library sigset modified, but the signal would never be unblocked.
Now we unblock the signal after reseting the handler...

This commit was SVN r7623.
2005-10-04 19:01:13 +00:00

282 строки
7.1 KiB
C

/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
/*
* Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ompi_config.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <sys/_time.h>
#endif
#include <sys/queue.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <errno.h>
#include <err.h>
#include <fcntl.h>
#ifdef USE_LOG
#include "log.h"
#else
#define LOG_DBG(x)
#define log_error(x) perror(x)
#endif
#include "event.h"
#include "evsignal.h"
#include "opal/util/output.h"
extern struct opal_event_list opal_signalqueue;
extern const struct opal_eventop *opal_evsel;
extern void *opal_evbase;
static short opal_evsigcaught[NSIG];
static int opal_needrecalc;
#if 0
static int opal_event_signal_pipe[2];
static opal_event_t opal_event_signal_pipe_event;
#endif
volatile sig_atomic_t opal_event_signal_count = 0;
static bool initialized = false;
volatile sig_atomic_t opal_evsignal_caught = 0;
#if 0
static void opal_event_signal_pipe_handler(int sd, short flags, void* user)
{
opal_output(0, "opal_event_signal_pipe_handler: %d\n", opal_event_signal_count);
while(opal_event_signal_count-- > 0) {
char byte;
read(opal_event_signal_pipe[0], &byte, 1);
}
}
#endif
void opal_evsignal_handler(int sig);
void
opal_evsignal_init(sigset_t *evsigmask)
{
#ifndef WIN32
sigemptyset(evsigmask);
#endif
}
int
opal_evsignal_add(sigset_t *evsigmask, struct opal_event *ev)
{
int evsignal;
if (!initialized) {
opal_event_signal_count = 0;
#if 0
/* Must delay the event add until after init() because
it may trigger poll events that are not yet setup
to be triggered. */
pipe(opal_event_signal_pipe);
opal_event_set(&opal_event_signal_pipe_event,
opal_event_signal_pipe[0],
OPAL_EV_READ|OPAL_EV_PERSIST,
opal_event_signal_pipe_handler,
0);
opal_event_add_i(&opal_event_signal_pipe_event, 0);
#endif
initialized = true;
}
if (ev->ev_events & (OPAL_EV_READ|OPAL_EV_WRITE))
errx(1, "%s: OPAL_EV_SIGNAL incompatible use", __func__);
evsignal = OPAL_EVENT_SIGNAL(ev);
/* force a recalc of the events we are waiting for, otherwise
events aren't recalculated until the next time event_loop
is called. Since that might not be for some time, that
gives a window where a signal handler *should* be installed
but actually is not. */
if (opal_evsel->recalc && opal_evsel->recalc(opal_evbase, 0) == -1) {
opal_output(0, "opal_event_loop: opal_evsel->recalc() failed.");
opal_mutex_unlock(&opal_event_lock);
return (-1);
}
#ifndef WIN32
sigaddset(evsigmask, evsignal);
#endif
return (0);
}
int
opal_evsignal_restart(void)
{
if(initialized) {
opal_event_signal_count = 0;
#if 0
int rc;
opal_event_del_i(&opal_event_signal_pipe_event);
if ((rc = pipe(opal_event_signal_pipe)) != 0) {
return rc;
}
opal_event_set(&opal_event_signal_pipe_event,
opal_event_signal_pipe[0],
OPAL_EV_READ|OPAL_EV_PERSIST,
opal_event_signal_pipe_handler,
0);
opal_event_add_i(&opal_event_signal_pipe_event, 0);
#endif
}
return (0);
}
/*
* Nothing to be done here.
*/
int
opal_evsignal_del(sigset_t *evsigmask, struct opal_event *ev)
{
#ifdef WIN32
return 0;
#else
int evsignal, ret;
struct sigaction sa;
sigset_t set;
evsignal = OPAL_EVENT_SIGNAL(ev);
/* remove from the "in use" signal list */
sigdelset(evsigmask, evsignal);
opal_needrecalc = 1;
/* set back to default handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
ret = sigaction(evsignal, &sa, NULL);
/* unblock signal, in case we were blocking the "in use" signals
when this function was called */
sigemptyset(&set);
sigaddset(&set, evsignal);
sigprocmask(SIG_UNBLOCK, &set, NULL);
return ret;
#endif
}
void
opal_evsignal_handler(int sig)
{
#if 0
unsigned char byte = 0;
#endif
opal_evsigcaught[sig]++;
opal_evsignal_caught = 1;
#if 0
if(opal_event_signal_count == 0) {
opal_event_signal_count++;
write(opal_event_signal_pipe[1], &byte, 1);
}
#endif
}
int
opal_evsignal_recalc(sigset_t *evsigmask)
{
#ifdef WIN32
return 0;
#else
struct sigaction sa;
struct opal_event *ev;
if (TAILQ_FIRST(&opal_signalqueue) == NULL && !opal_needrecalc)
return (0);
opal_needrecalc = 0;
if (sigprocmask(SIG_BLOCK, evsigmask, NULL) == -1)
return (-1);
/* Reinstall our signal handler. */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = opal_evsignal_handler;
sa.sa_mask = *evsigmask;
#if OMPI_HAVE_SA_RESTART
sa.sa_flags |= SA_RESTART;
#endif
TAILQ_FOREACH(ev, &opal_signalqueue, ev_signal_next) {
if (sigaction(OPAL_EVENT_SIGNAL(ev), &sa, NULL) == -1)
return (-1);
}
return (0);
#endif
}
int
opal_evsignal_deliver(sigset_t *evsigmask)
{
if (TAILQ_FIRST(&opal_signalqueue) == NULL)
return (0);
#ifdef WIN32
return 0;
#else
return (sigprocmask(SIG_UNBLOCK, evsigmask, NULL));
/* XXX - pending signals handled here */
#endif
}
void
opal_evsignal_process(void)
{
struct opal_event *ev;
short ncalls;
TAILQ_FOREACH(ev, &opal_signalqueue, ev_signal_next) {
ncalls = opal_evsigcaught[OPAL_EVENT_SIGNAL(ev)];
if (ncalls) {
if (!(ev->ev_events & OPAL_EV_PERSIST))
opal_event_del_i(ev);
opal_event_active_i(ev, OPAL_EV_SIGNAL, ncalls);
}
}
memset(opal_evsigcaught, 0, sizeof(opal_evsigcaught));
opal_evsignal_caught = 0;
}