From: ware@oboe.cis.ohio-state.edu (Peter Ware)
Newsgroups: comp.windows.x
Subject: Re: Why X libraries are not reentrant?
Date: 22 Jan 1993 08:55:43 -0500
Organization: Ohio State Computer Science
	<1993Jan19.025831.19583@thunder.mcrcim.mcgill.edu>
	<1993Jan20.090241.1810@cenatls.cena.dgac.fr>
	<1993Jan21.171844.23941@jpl-devvax.jpl.nasa.gov>
NNTP-Posting-Host: oboe.cis.ohio-state.edu
In-reply-to: kaleb@swat's message of Thu, 21 Jan 1993 17:18:44 GMT

The following code, which I'll someday include in the Xt-FAQ,
implements signal handling using pipes.

--pete

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	signals.c
#	sighandler.h
# This archive created: Fri Jan 22 08:54:10 1993
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'signals.c'
then
	echo shar: "will not over-write existing file 'signals.c'"
else
cat << \SHAR_EOF > 'signals.c'
/*
 * signals -
 *	An Xt Intrinsics signal handler developed based on discussions
 *	in comp.windows.x and written by someone who wishes to be
 *	anonymous.
 *
 *	A pipe is created and the read side is passed off to
 *	XtAppAddInput().  Everytime a signal occurs a byte, indicating
 *	which signal, is written by the signal handler on the write
 *	side of the pipe.  This causes the Intrinsics to call the
 *	input handler which then invokes the correct callback.
 *
 *	The potential for deadlock exists if the pipe is ever filled!
 *
 * $Id: signals.c,v 1.1 92/12/10 08:51:01 ware Exp $
 * $Log:	signals.c,v $
 * Revision 1.1  92/12/10  08:51:01  ware
 * Initial revision
 * 
 */

#include <X11/Intrinsic.h>
#include <signal.h>		/* signal stuff */
#include <sys/types.h>		/* for pipe */
#include <string.h>		/* for memset */
#include "sighandler.h"

static _XoSignalData sig_info[NSIG + 1]; /* NSIG is max signal value */

static int pipefd [2];			/* the input & output pipes */

static void _xsig_handler (
#if NeedFunctionPrototypes
	int	sig,
	int	code
#endif
);

static void
_xsig_pipe_handler (
#if NeedFunctionPrototypes
	XtPointer	client_data,
	int		*source,
	XtInputId	*id
#endif
);

/*
 * XoAppAddSignal -
 *	Install a handler for a particular signal.  There can be only
 *	a single handler per signal (it might be nice to use a callback).
 */

void
XoAppAddSignal (context, sig, handler, client_data)
	XtAppContext	context;	/* application context */
	int		sig;		/* which signal */
	XoSignalCallbackProc handler;	/* the handler */
	XtPointer	client_data;	/* private data */
{
	static int firsttime = True;

	/*
	 * We need to create the pipe and tell the intrinsics about
	 * the new file descriptor
	 */
	if (firsttime)
	{
		firsttime = False;
		pipe (pipefd);
		XtAppAddInput (context, pipefd [0],
			       (XtPointer) XtInputReadMask,
			       _xsig_pipe_handler, (XtPointer) NULL);
	}
	signal (sig, _xsig_handler);
	sig_info[sig].handler = handler;
	sig_info[sig].client_data = client_data;
}				/* XoAppAddSignal */

/*
 * XoAppRemoveSignal -
 *	Uninstalls a handler for a particular signal.  The values
 *	of handler and client_data most match in order to remove the
 *	particular signal handler.  If there are no more remaining
 *	signal handlers for that signal then SIG_DFL is installed.
 *
 *	Of course, the current implementation only allows one handler
 *	per signal but in the future when multiple ones are added this
 *	will continue to work.  The application context is not used
 *	and is left merely for consistency.
 */

void
XoAppRemoveSignal (context, sig, handler, client_data)
	XtAppContext	context;	/* application context */
	int		sig;		/* which signal */
	XoSignalCallbackProc handler;	/* the handler */
	XtPointer	client_data;	/* private data */
{
	signal (sig, SIG_DFL);	/* restore old signal handler */
	sig_info [sig].handler = (XtInputCallbackProc) NULL;
	sig_info [sig].client_data = NULL;
}				/* XoAppRemoveSignal */

/*
 * _xsig_handler -
 *	the actual signal handler (custom), writes a byte to a pipe
 */
static void
_xsig_handler (sig, code)
	int	sig;
	int	code;
{
	char	sig_value;
	
	sig_value = sig;
	write (pipefd [1], &sig_value, 1);
}				/* _xsig_handler */

/*
 * _xsig_pipe_handler -
 *	reads input from the pipe and executes the corresponding callback.
 */

static void
_xsig_pipe_handler (client_data, source, id)
	XtPointer	client_data;
	int		*source;
	XtInputId	*id;
{
	unsigned char	sig_value;
	int		sig;
	
	read (pipefd [0], &sig_value, 1);
	sig = sig_value;
	if (sig > 0 && sig < NSIG && sig_info[sig].handler)
		(*sig_info [sig].handler) (sig, sig_info[sig].client_data);
}				/* _xsig_pipe_handler */
SHAR_EOF
fi
if test -f 'sighandler.h'
then
	echo shar: "will not over-write existing file 'sighandler.h'"
else
cat << \SHAR_EOF > 'sighandler.h'
/*
 * sighandler.h -
 *	Defines the interface to signalling handling in an Xt save way
 * $Id: sighandler.h,v 1.1 92/12/10 08:50:54 ware Exp $
 * $Log:	sighandler.h,v $
 * Revision 1.1  92/12/10  08:50:54  ware
 * Initial revision
 * 
 */

typedef void (*XoSignalCallbackProc) (
#if NeedFunctionPrototypes
	int		signo,		/* the signal number */
	XtPointer 	client_data	/* closure */
#endif
);

/*
 * Private structure used to store the information about the currently
 * installed signal handlers
 */

typedef struct _xo_signal_data_
{
	XoSignalCallbackProc	handler; /* function to execute */
	XtPointer		client_data; /* data to pass */
} _XoSignalData;

extern void XoAppAddSignal (
#if NeedFunctionPrototypes
	XtAppContext	context,	/* application context */
	int		sig,		/* which signal */
	XoSignalCallbackProc handler,	/* the handler */
	XtPointer	client_data	/* private data */
#endif
);

extern void XoAppRemoveSignal (
#if NeedFunctionPrototypes
	XtAppContext	context,	/* application context */
	int		sig,		/* which signal */
	XoSignalCallbackProc handler,	/* the handler */
	XtPointer	client_data	/* private data */
#endif
);


SHAR_EOF
fi
exit 0
#	End of shell archive
--
Pete Ware					ware@cis.ohio-state.edu
CIS Dept, Ohio State University			w/ (614) 292-7318
228 Bolz Hall, 2036 Neil Ave.			h/ (614) 538-0965
Columbus, OH 43210
Welcome William Patrick Ware to the world!  Born 10/21/92, 8lbs 6.2oz (3.83kg)