Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  watchdog.c

  Sprache: C
 

/*++
/* NAME
/* watchdog 3
/* SUMMARY
/* watchdog timer
/* SYNOPSIS
/* #include <watchdog.h>
/*
/* WATCHDOG *watchdog_create(timeout, action, context)
/* unsigned timeout;
/* void (*action)(WATCHDOG *watchdog, char *context);
/* char *context;
/*
/* void watchdog_start(watchdog)
/* WATCHDOG *watchdog;
/*
/* void watchdog_stop(watchdog)
/* WATCHDOG *watchdog;
/*
/* void watchdog_destroy(watchdog)
/* WATCHDOG *watchdog;
/*
/* void watchdog_pat()
/* DESCRIPTION
/* This module implements watchdog timers that are based on ugly
/* UNIX alarm timers. The module is designed to survive systems
/* with clocks that jump occasionally.
/*
/* Watchdog timers can be stacked. Only one watchdog timer can be
/* active at a time. Only the last created watchdog timer can be
/* manipulated. Watchdog timers must be destroyed in reverse order
/* of creation.
/*
/* watchdog_create() suspends the current watchdog timer, if any,
/* and instantiates a new watchdog timer.
/*
/* watchdog_start() starts or restarts the watchdog timer.
/*
/* watchdog_stop() stops the watchdog timer.
/*
/* watchdog_destroy() stops the watchdog timer, and resumes the
/* watchdog timer instance that was suspended by watchdog_create().
/*
/* watchdog_pat() pats the watchdog, so it stays quiet.
/*
/* Arguments:
/* .IP timeout
/* The watchdog time limit. When the watchdog timer runs, the
/* process must invoke watchdog_start(), watchdog_stop() or
/* watchdog_destroy() before the time limit is reached.
/* .IP action
/* A null pointer, or pointer to function that is called when the
/* watchdog alarm goes off. The default action is to terminate
/* the process with a fatal error.
/* .IP context
/* Application context that is passed to the action routine.
/* .IP watchdog
/* Must be a pointer to the most recently created watchdog instance.
/* This argument is checked upon each call.
/* BUGS
/* UNIX alarm timers are not stackable, so there can be at most one
/* watchdog instance active at any given time.
/* SEE ALSO
/* msg(3) diagnostics interface
/* DIAGNOSTICS
/* Fatal errors: memory allocation problem, system call failure.
/* Panics: interface violations.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/


/* System library. */

#include <sys_defs.h>
#include <unistd.h>
#include <signal.h>
#include <posix_signals.h>

/* Utility library. */

#include <msg.h>
#include <mymalloc.h>
#include <killme_after.h>
#include <watchdog.h>

/* Application-specific. */

 /*
  * Rather than having one timer that goes off when it is too late, we break
  * up the time limit into smaller intervals so that we can deal with clocks
  * that jump occasionally.
  */

#define WATCHDOG_STEPS 3

 /*
  * UNIX alarms are not stackable, but we can save and restore state, so that
  * watchdogs can at least be nested, sort of.
  */

struct WATCHDOG {
    unsigned timeout;   /* our time resolution */
    WATCHDOG_FN action;   /* application routine */
    char   *context;   /* application context */
    int     trip_run;   /* number of successive timeouts */
    WATCHDOG *saved_watchdog;  /* saved state */
    struct sigaction saved_action; /* saved state */
    unsigned saved_time;  /* saved state */
};

 /*
  * However, only one watchdog instance can be current, and the caller has to
  * restore state before a prior watchdog instance can be manipulated.
  */

static WATCHDOG *watchdog_curr;

 /*
  * Workaround for systems where the alarm signal does not wakeup the event
  * machinery, and therefore does not restart the watchdog timer in the
  * single_server etc. skeletons. The symptom is that programs abort when the
  * watchdog timeout is less than the max_idle time.
  */

#ifdef USE_WATCHDOG_PIPE
#include <errno.h>
#include <iostuff.h>
#include <events.h>

static int watchdog_pipe[2];

/* watchdog_read - read event pipe */

static void watchdog_read(int unused_event, void *unused_context)
{
    char    ch;

    while (read(watchdog_pipe[0], &ch, 1) > 0)
  /* void */ ;
}

#endif     /* USE_WATCHDOG_PIPE */

/* watchdog_event - handle timeout event */

static void watchdog_event(int unused_sig)
{
    const char *myname = "watchdog_event";
    WATCHDOG *wp;

    /*
     * This routine runs as a signal handler. We should not do anything that
     * could involve memory allocation/deallocation, but exiting without
     * proper explanation would be unacceptable. For this reason, msg(3) was
     * made safe for usage by signal handlers that terminate the process.
     */

    if ((wp = watchdog_curr) == 0)
 msg_panic("%s: no instance", myname);
    if (msg_verbose > 1)
 msg_info("%s: %p %d", myname, (void *) wp, wp->trip_run);
    if (++(wp->trip_run) < WATCHDOG_STEPS) {
#ifdef USE_WATCHDOG_PIPE
 int     saved_errno = errno;

 /* Wake up the events(3) engine. */
 if (write(watchdog_pipe[1], ""1) != 1)
     msg_warn("%s: write watchdog_pipe: %m", myname);
 errno = saved_errno;
#endif
 alarm(wp->timeout);
    } else {
 if (wp->action)
     wp->action(wp, wp->context);
 else {
     killme_after(5);
#ifdef TEST
     pause();
#endif
     msg_fatal("watchdog timeout");
 }
    }
}

/* watchdog_create - create watchdog instance */

WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context)
{
    const char *myname = "watchdog_create";
    struct sigaction sig_action;
    WATCHDOG *wp;

    wp = (WATCHDOG *) mymalloc(sizeof(*wp));
    if ((wp->timeout = timeout / WATCHDOG_STEPS) == 0)
 msg_panic("%s: timeout %d is too small", myname, timeout);
    wp->action = action;
    wp->context = context;
    wp->saved_watchdog = watchdog_curr;
    wp->saved_time = alarm(0);
    sigemptyset(&sig_action.sa_mask);
#ifdef SA_RESTART
    sig_action.sa_flags = SA_RESTART;
#else
    sig_action.sa_flags = 0;
#endif
    sig_action.sa_handler = watchdog_event;
    if (sigaction(SIGALRM, &sig_action, &wp->saved_action) < 0)
 msg_fatal("%s: sigaction(SIGALRM): %m", myname);
    if (msg_verbose > 1)
 msg_info("%s: %p %d", myname, (void *) wp, timeout);
#ifdef USE_WATCHDOG_PIPE
    if (watchdog_curr == 0) {
 if (pipe(watchdog_pipe) < 0)
     msg_fatal("%s: pipe: %m", myname);
 non_blocking(watchdog_pipe[0], NON_BLOCKING);
 non_blocking(watchdog_pipe[1], NON_BLOCKING);
 close_on_exec(watchdog_pipe[0], CLOSE_ON_EXEC); /* Fix 20190126 */
 close_on_exec(watchdog_pipe[1], CLOSE_ON_EXEC); /* Fix 20190126 */
 event_enable_read(watchdog_pipe[0], watchdog_read, (void *) 0);
    }
#endif
    return (watchdog_curr = wp);
}

/* watchdog_destroy - destroy watchdog instance, restore state */

void    watchdog_destroy(WATCHDOG *wp)
{
    const char *myname = "watchdog_destroy";

    watchdog_stop(wp);
    watchdog_curr = wp->saved_watchdog;
    if (sigaction(SIGALRM, &wp->saved_action, (struct sigaction *) 0) < 0)
 msg_fatal("%s: sigaction(SIGALRM): %m", myname);
    if (wp->saved_time)
 alarm(wp->saved_time);
    myfree((void *) wp);
#ifdef USE_WATCHDOG_PIPE
    if (watchdog_curr == 0) {
 event_disable_readwrite(watchdog_pipe[0]);
 (void) close(watchdog_pipe[0]);
 (void) close(watchdog_pipe[1]);
    }
#endif
    if (msg_verbose > 1)
 msg_info("%s: %p", myname, (void *) wp);
}

/* watchdog_start - enable watchdog timer */

void    watchdog_start(WATCHDOG *wp)
{
    const char *myname = "watchdog_start";

    if (wp != watchdog_curr)
 msg_panic("%s: wrong watchdog instance", myname);
    wp->trip_run = 0;
    alarm(wp->timeout);
    if (msg_verbose > 1)
 msg_info("%s: %p", myname, (void *) wp);
}

/* watchdog_stop - disable watchdog timer */

void    watchdog_stop(WATCHDOG *wp)
{
    const char *myname = "watchdog_stop";

    if (wp != watchdog_curr)
 msg_panic("%s: wrong watchdog instance", myname);
    alarm(0);
    if (msg_verbose > 1)
 msg_info("%s: %p", myname, (void *) wp);
}

/* watchdog_pat - pat the dog so it stays quiet */

void    watchdog_pat(void)
{
    const char *myname = "watchdog_pat";

    if (watchdog_curr)
 watchdog_curr->trip_run = 0;
    if (msg_verbose > 1)
 msg_info("%s: %p", myname, (void *) watchdog_curr);
}

#ifdef TEST

#include <vstream.h>

int     main(int unused_argc, char **unused_argv)
{
    WATCHDOG *wp;

    msg_verbose = 2;

    wp = watchdog_create(10, (WATCHDOG_FN) 0, (void *) 0);
    watchdog_start(wp);
    do {
 watchdog_pat();
    } while (VSTREAM_GETCHAR() != VSTREAM_EOF);
    watchdog_destroy(wp);
    return (0);
}

#endif

Messung V0.5 in Prozent
C=83 H=93 G=87

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002