Glib bits'n'pieces



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi folks,

After a post a few weeks ago about writing a GSource for UNIX signals,
I spent a few nights writing one, which is now mostly done (I've
attached the header; any comments would be appreciated).  The main
issue I have is how to avoid overrunning the signal buffer if flooded
with signals before the mainloop runs (I can't realloc memory in a
signal handler, so I rely on a fixed-length g_renew'd buffer which is
resized in the mainloop if needed, but by that time I've lost data).
I also realised that what I really wanted was for the GSource to be a
GObject, so that I could connect multiple event handlers rather than a
single callback.  The reason for this is that due to signals being
coarse-grained (per-process), the handler object has to be a
singleton, and so I wanted the handlers to work like GdkEvents, where
if I can't (or don't want to) handle a particular event, I return
FALSE and let the next handler process it.  However, this is not
currently possible, restricting me to a single handler function per
process, which is not extensible.

Looking at GSource itself, it looks like it would be cleaner and
easier to use if it was a GObject, and the same applies to quite a
number of glib types, including the container types.  If the list
types, for example, were GObjects, some operations would become rather
more efficient if the object was a list head, which would then allow
for caching, and not returning the first GList node for every
operation changing the list saves needlessly traversing the list when
e.g. appending.  It might also be possible to restrict the list
contents to a particular GType, set callbacks for automatic sorting,
freeing nodes etc., and store GValues rather than gpointers in the
nodes.  This would also provide the opportunity to add common
container interfaces e.g. GIterator, GContainer for all container
types (which could also be implemented by e.g. GtkContainer).


Are any changes like this planned for glib 3.x?


Thanks,
Roger


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

#include <glib/gtypes.h>
#include <glib/gmain.h>

typedef struct _GUnixSignalAny GUnixSignalAny;
typedef struct _GUnixSignalIllegal GUnixSignalIllegal;
typedef struct _GUnixSignalFpe GUnixSignalFpe;
typedef struct _GUnixSignalSegv GUnixSignalSegv;
typedef struct _GUnixSignalBus GUnixSignalBus;
typedef struct _GUnixSignalTrap GUnixSignalTrap;
typedef struct _GUnixSignalChild GUnixSignalChild;
typedef struct _GUnixSignalPoll GUnixSignalPoll;

typedef union _GUnixSignal GUnixSignal;

typedef void (*GUnixSignalFunc)(GUnixSignal *signal,
				gpointer     user_data);

typedef enum
{
#ifdef SIGHUP
  G_UNIX_SIGNAL_HANGUP    = SIGHUP,
#endif
#ifdef SIGINT
  G_UNIX_SIGNAL_INTERRUPT = SIGINT,
#endif
#ifdef SIGQUIT
  G_UNIX_SIGNAL_QUIT      = SIGQUIT,
#endif
#ifdef SIGILL
  G_UNIX_SIGNAL_ILLEGAL   = SIGILL,
#endif
#ifdef SIGABRT
  G_UNIX_SIGNAL_ABORT     = SIGABRT,
#endif
#ifdef SIGFPE
  G_UNIX_SIGNAL_FPE       = SIGFPE,
#endif
#ifdef SIGKILL
  G_UNIX_SIGNAL_KILL      = SIGKILL,
#endif
#ifdef SIGSEGV
  G_UNIX_SIGNAL_SEGV      = SIGSEGV,
#endif
#ifdef SIGPIPE
  G_UNIX_SIGNAL_PIPE      = SIGPIPE,
#endif
#ifdef SIGALRM
  G_UNIX_SIGNAL_ALARM     = SIGALRM,
#endif
#ifdef SIGTERM
  G_UNIX_SIGNAL_TERMINATE = SIGTERM,
#endif
#ifdef SIGUSR1
  G_UNIX_SIGNAL_USER1     = SIGUSR1,
#endif
#ifdef SIGUSR2
  G_UNIX_SIGNAL_USER2     = SIGUSR2,
#endif
#ifdef SIGCHLD
  G_UNIX_SIGNAL_CHILD     = SIGCHLD,
#endif
#ifdef SIGCONT
  G_UNIX_SIGNAL_CONTINUE  = SIGCONT,
#endif
#ifdef SIGSTOP
  G_UNIX_SIGNAL_STOP      = SIGSTOP,
#endif
#ifdef SIGTSTP
  G_UNIX_SIGNAL_TTYSTOP   = SIGTSTP,
#endif
#ifdef SIGTTIN
  G_UNIX_SIGNAL_TTYINPUT  = SIGTTIN,
#endif
#ifdef SIGTTOU
  G_UNIX_SIGNAL_TTYOUTPUT = SIGTTOU
#endif
} GUnixSignalType;

typedef enum
{
#ifdef SI_ASYNCNL
  G_UNIX_SIGNAL_TYPE_ASYNC_NAME_LOOKUP	= SI_ASYNCNL,
#endif
#ifdef SI_TKILL
  G_UNIX_SIGNAL_TYPE_TKILL		= SI_TKILL,
#endif
#ifdef SI_SIGIO
  G_UNIX_SIGNAL_TYPE_SIGIO		= SI_SIGIO,
#endif
#ifdef SI_ASYNCIO
  G_UNIX_SIGNAL_TYPE_ASYNC_IO		= SI_ASYNCIO,
#endif
#ifdef SI_MESGQ
  G_UNIX_SIGNAL_TYPE_MESSAGEG_QUEUE	= SI_MESGQ,
#endif
#ifdef SI_TIMER
  G_UNIX_SIGNAL_TYPE_TIMER		= SI_TIMER,
#endif
#ifdef SI_QUEUE
  G_UNIX_SIGNAL_TYPE_QUEUE		= SI_QUEUE,
#endif
#ifdef SI_USER
  G_UNIX_SIGNAL_TYPE_USER		= SI_USER,
#endif
#ifdef SI_KERNEL
  G_UNIX_SIGNAL_TYPE_KERNEL		= SI_KERNEL,
#endif
  G_UNIX_SIGNAL_TYPE_SPECIFIC
} GUnixSignalCode;

typedef enum
{
#ifdef ILL_ILLOPC
  G_UNIX_SIGNAL_ILLEGAL_OPCODE		= ILL_ILLOPC,
#endif
#ifdef ILL_ILLOPN
  G_UNIX_SIGNAL_ILLEGAL_OPERAND		= ILL_ILLOPN,
#endif
#ifdef ILL_ILLADR
  G_UNIX_SIGNAL_ILLEGAL_ADDRESS		= ILL_ILLADR,
#endif
#ifdef ILL_ILLTRP
  G_UNIX_SIGNAL_ILLEGAL_TRAP		= ILL_ILLTRP,
#endif
#ifdef ILL_PRVOPC
  G_UNIX_SIGNAL_ILLEGAL_PRIV_OPCODE	= ILL_PRVOPC,
#endif
#ifdef ILL_PRVREG
  G_UNIX_SIGNAL_ILLEGAL_PRIV_REGISTER	= ILL_PRVREG,
#endif
#ifdef ILL_COPROC
  G_UNIX_SIGNAL_ILLEGAL_COPROCESSOR	= ILL_COPROC,
#endif
#ifdef ILL_BADSTK
  G_UNIX_SIGNAL_ILLEGAL_STACK		= ILL_BADSTK
#endif
} GUnixSignalIllegalCode;

typedef enum
{
#ifdef FPE_INTDIV
  G_UNIX_SIGNAL_INTEGER_ZERO_DIVIDE	= FPE_INTDIV,
#endif
#ifdef FPE_INTOVF
  G_UNIX_SIGNAL_INTEGER_OVERFLOW	= FPE_INTOVF,
#endif
#ifdef FPE_FLTDIV
  G_UNIX_SIGNAL_FLOAT_ZERO_DIVIDE	= FPE_FLTDIV,
#endif
#ifdef FPE_FLTOVF
  G_UNIX_SIGNAL_FLOAT_OVERFLOW		= FPE_FLTOVF,
#endif
#ifdef FPE_FLTUND
  G_UNIX_SIGNAL_FLOAT_UNDERFLOW		= FPE_FLTUND,
#endif
#ifdef FPE_FLTRES
  G_UNIX_SIGNAL_FLOAT_INEXACT		= FPE_FLTRES,
#endif
#ifdef FPE_FLTINV
  G_UNIX_SIGNAL_FLOAT_INVALID		= FPE_FLTINV,
#endif
#ifdef FPE_FLTSUB
  G_UNIX_SIGNAL_FLOAT_SUBSCRIPT_RANGE	= FPE_FLTSUB
#endif
} GUnixSignalFpeCode;

typedef enum
{
#ifdef SEGV_MAPERR
  G_UNIX_SIGNAL_SEGV_MAP_ERROR		= SEGV_MAPERR,
#endif
#ifdef SEGV_ACCERR
  G_UNIX_SIGNAL_SEGV_ACCESS_ERROR	= SEGV_ACCERR
#endif
} GUnixSignalSegvCode;

typedef enum
{
#ifdef BUS_ADRALN
  G_UNIX_SIGNAL_BUS_ADDRESS_ALIGNMENT	= BUS_ADRALN,
#endif
#ifdef BUS_ADRERR
  G_UNIX_SIGNAL_BUS_ADDRESS_ERROR	= BUS_ADRERR,
#endif
#ifdef BUS_OBJERR
  G_UNIX_SIGNAL_BUS_OBJECT_ERROR	= BUS_OBJERR
#endif
} GUnixSignalBusCode;

typedef enum
{
#ifdef TRAP_BRKPT
  G_UNIX_SIGNAL_TRAP_BREAKPOINT	= TRAP_BRKPT,
#endif
#ifdef TRAP_TRACE
  G_UNIX_SIGNAL_TRAP_TRACE	= TRAP_TRACE
#endif
} GUnixSignalTrapCode;

typedef enum
{
#ifdef CLD_EXITED
  G_UNIX_SIGNAL_CHILD_EXITED	= CLD_EXITED,
#endif
#ifdef CLD_KILLED
  G_UNIX_SIGNAL_CHILD_KILLED	= CLD_KILLED,
#endif
#ifdef CLD_DUMPED
  G_UNIX_SIGNAL_CHILD_DUMPED	= CLD_DUMPED,
#endif
#ifdef CLD_TRAPPED
  G_UNIX_SIGNAL_CHILD_TRAPPED	= CLD_TRAPPED,
#endif
#ifdef CLD_STOPPED
  G_UNIX_SIGNAL_CHILD_STOPPED	= CLD_STOPPED,
#endif
#ifdef CLD_CONTINUED
  G_UNIX_SIGNAL_CHILD_CONTINUED	= CLD_CONTINUED
#endif
} GUnixSignalChildCode;

typedef enum
{
#ifdef POLL_IN
  G_UNIX_SIGNAL_POLL_INPUT	= POLL_IN,
#endif
#ifdef POLL_OUT
  G_UNIX_SIGNAL_POLL_OUTPUT	= POLL_OUT,
#endif
#ifdef POLL_MSG
  G_UNIX_SIGNAL_POLL_MESSAGE	= POLL_MSG,
#endif
#ifdef POLL_ERR
  G_UNIX_SIGNAL_POLL_ERROR	= POLL_ERR,
#endif
#ifdef POLL_PRI
  G_UNIX_SIGNAL_POLL_PRIORITY	= POLL_PRI,
#endif
#ifdef POLL_HUP
  G_UNIX_SIGNAL_POLL_HANGUP	= POLL_HUP
#endif
} GUnixSignalPollCode;


struct _GUnixSignalAny
{
  GUnixSignalType	type;
  int			errno;
  GUnixSignalCode	code;
};

struct _GUnixSignalIllegal
{
  GUnixSignalType		 type;
  int				 errno;
  GUnixSignalCode		 code;
  GUnixSignalIllegalCode	 scode;
  void				*addr;
};

struct _GUnixSignalFpe
{
  GUnixSignalType	 type;
  int			 errno;
  GUnixSignalCode	 code;
  GUnixSignalFpeCode	 scode;
  void			*addr;
};

struct _GUnixSignalSegv
{
  GUnixSignalType	 type;
  int			 errno;
  GUnixSignalCode	 code;
  GUnixSignalSegvCode	 scode;
  void			*addr;
};

struct _GUnixSignalBus
{
  GUnixSignalType	 type;
  int			 errno;
  GUnixSignalCode	 code;
  GUnixSignalBusCode	 scode;
  void			*addr;
};

struct _GUnixSignalTrap
{
  GUnixSignalType	type;
  int			errno;
  GUnixSignalCode	code;
  GUnixSignalTrapCode	scode;
};

struct _GUnixSignalChild
{
  GUnixSignalType	type;
  int			errno;
  GUnixSignalCode	code;
  GUnixSignalChildCode	scode;
  pid_t			pid;
  uid_t			uid;
  int			status;
  clock_t		utime;
  clock_t		stime;
};

struct _GUnixSignalPoll
{
  GUnixSignalType	type;
  int			errno;
  GUnixSignalCode	code;
  GUnixSignalPollCode	scode;
  int			band;
  int			fd;
};

union _GUnixSignal
{
  GUnixSignalType	type;
  GUnixSignalAny	any;
  GUnixSignalIllegal	illegal;
  GUnixSignalFpe	fpe;
  GUnixSignalSegv	segv;
  GUnixSignalBus	bus;
  GUnixSignalTrap	trap;
  GUnixSignalChild	child;
  GUnixSignalPoll	poll;
};

GSource *
g_unix_signal_create_watch (void);


- -- 
Roger Leigh
                Printing on GNU/Linux?  http://gimp-print.sourceforge.net/
                Debian GNU/Linux        http://www.debian.org/
                GPG Public Key: 0x25BFB848.  Please sign and encrypt your mail.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
Comment: Processed by Mailcrypt 3.5.8 <http://mailcrypt.sourceforge.net/>

iD8DBQFCa3HZVcFcaSW/uEgRAlI7AJ9j7LL2xxj+PRFXKQv4krcI1+1RTQCg1AvI
CB2yxA435KZ33xJlOg3WVN8=
=YJIJ
-----END PGP SIGNATURE-----



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]