Subject: Trial module check - does it configure / compile?

From: Chris Rankin <[email-masked]>
Date: Sat, 8 May 1999 19:24:32 +1000 (EST)

Hi,
Down to the nitty-gritty bits with this signal stuff, then. I have
written a small module which should probably go into
libfvwm.a. Nothing uses it yet - this is just a test to see if
autoconf can handle it and what else I need to put into it.

config.h already contains HAVE_SIGACTION and a typedef for
sig_atomic_t; I expect that it will also need checks for HAVE_SIGBLOCK
and HAVE_SIGSETMASK in case the system doesn't support POSIX.1. It
should compile cleanly on any POSIX.1 system

Cheers,
Chris.

--snip----------------------------------------------------------------------
#ifndef FVWMSIGNAL_H
#define FVWMSIGNAL_H

/***************************************************************************
 * This module provides wrappers around system functions that could
 * potentially block, e.g. select(). These wrappers will check that
 * the "terminate" flag is still clear and then call the system
 * function in one atomic operation. This ensures that FVWM will not
 * block in a system function once it has received the signal to quit.
 *
 * This module was written by Chris Rankin,  [email-masked]
 ***************************************************************************/

/***************************************************************************
 * This module is intended to use POSIX.1 signal semantics, since most
 * modern systems can reasonably be expected to support POSIX and since
 * the semantics of the old "signal()" function vary from system to system.
 * If POSIX.1 is not available then the module can provide BSD signal
 * semantics, which can be summarised as follows:
 *  - the signal handler will NOT uninstall itself once it has been called
 *  - a signal will be temporarily blocked from further delivery so long
 *    as its handler is running
 *  - certain system calls will be automatically restarted if interrupted
 *    by a signal
 */

#if !defined(HAVE_SIGACTION) \
    && defined(HAVE_SIGBLOCK) && defined(HAVE_SIGSETMASK)
#  define USE_BSD_SIGNALS
#endif

#include <signal.h>
#include <sys/time.h>

/***************************************************************************
 * Global variables
 */
extern volatile sig_atomic_t isTerminated;

/***************************************************************************
 * Module prototypes
 */
extern void fvwmSetTerminate(void);

extern int fvwmSelect(int nfds,
                      fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
                      struct timeval *timeout);

#endif /* FVWMSIGNAL_H */

--snip---------------------------------------------------------------------
/***************************************************************************
 * fvwmsignal.c
 * Written by Chris Rankin,  [email-masked]
 *
 ***************************************************************************/

#include "config.h"

#include <setjmp.h>
#include <errno.h>
#include "fvwmsignal.h"

#define true   1
#define false  0

typedef enum { SIG_INIT=0, SIG_DONE } SIG_STATUS;

volatile sig_atomic_t isTerminated = false;

static volatile sig_atomic_t canJump = false;
static sigjmp_buf deadJump;

#ifdef USE_BSD_SIGNALS
#  error NOT IMPLEMENTED FULLY YET!!
static int term_sigs;
#endif

/************************************************************************
 * fvwmSetTerminate - set the "end-of-execution" flag.
 * This function should ONLY be called at the end of a
 * signal handler. It is an integral part of the mechanism
 * to stop system calls from blocking once the process is
 * finished. 
 *
 * NOTE: This is NOT a signal handler function in its own right!
 */
void
fvwmSetTerminate(void)
{
#ifdef USE_BSD_SIGNALS
  int old_mask = sigblock(term_sigs);
#endif
  isTerminated = true;

  if (canJump)
  {
    canJump = false;
    errno = EINTR;
    /*
     * This non-local jump is safe ONLY because we haven't called
     * any non-reentrant functions in the short period where the
     * "canJump" variable is true.
     *
     * NOTE: No need to restore the signal mask, since siglongjmp
     *       is designed to do that for us.
     */
    siglongjmp(deadJump, SIG_DONE);
  }
#ifdef USE_BSD_SIGNALS
  sigsetmask(old_mask);
#endif
}

/************************************************************************
 * fvwmSelect - wrapper around the select() system call.
 * This system call may block indefinitely. We don't want
 * to block at all if the "terminate" flag is set - we
 * just want it to fail as quickly as possible.
 */
int
fvwmSelect(int nfds,
           fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
           struct timeval *timeout)
{
  volatile int iRet = -1;  /* This variable MUST NOT be in a register */

  /*
   * Now initialise the non-local jump. Between here and the end of
   * the routine (more-or-less) we must NOT call any non-reentrant
   * functions! This is because we might need to abandon them half
   * way through execution and return here!
   */
  if ( sigsetjmp(deadJump, 1) == SIG_INIT )
  {
    /*
     * Activate the non-local jump. Between now and when we turn the
     * jump off again, we must NOT call any non-reentrant functions
     * because we could be interrupted halfway through ...
     */
    canJump = true;

    /*
     * If we have already been told to terminate then we will not
     * execute the select() because the flag will be set. If a
     * "terminate" signal arrives between testing the flag and
     * calling select() then we will jump back to the non-local
     * jump point ...
     */
    if ( !isTerminated )
    {
      /*
       * The "die" signal will interrupt this system call:
       * that IS the whole point, after all :-)
       */
      iRet = select(nfds, readfds, writefds, exceptfds, timeout);
    }

    /*
     * The non-local jump is about to go out of scope,
     * so we must deactivate it. Note that the return-
     * value from select() will be safely stored in the
     * local variable before the jump is disabled.
     */
    canJump = false;
  }

  return iRet;
}

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: [email-masked] (Paul D. Smith)
Date: 13 May 1999 12:35:55 -0400

This is not really related to the trial module per se, but I thought of
it while looking at the code.

What do people think about making the FVWM module header files C++ safe?
If folks wanted to write modules in C++ that seems like it would be the
neighborly thing to do.

Just a thought...

-- 
-------------------------------------------------------------------------------
 Paul D. Smith <[email-masked]>         Network Management Development
 "Please remain calm...I may be mad, but I am a professional." --Mad Scientist
-------------------------------------------------------------------------------
   These are my opinions---Nortel Networks takes no responsibility for them.
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Bob Woodside <[email-masked]>
Date: Thu, 13 May 1999 15:50:45 -0400

> If folks wanted to write modules in C++ that seems like it would be the

	Sounds like a good idea to me.

-Bob