svn commit: samba r20928 - in branches/SAMBA_4_0/source/lib/events: .

tridge at samba.org tridge at samba.org
Sun Jan 21 08:23:15 GMT 2007


Author: tridge
Date: 2007-01-21 08:23:14 +0000 (Sun, 21 Jan 2007)
New Revision: 20928

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=20928

Log:

added signal events to lib/events

Jeremy asked for this to allow Samba3 to use the Samba4 events library

see torture/local/event.c for an example

Added:
   branches/SAMBA_4_0/source/lib/events/events_signal.c
Modified:
   branches/SAMBA_4_0/source/lib/events/config.mk
   branches/SAMBA_4_0/source/lib/events/events.c
   branches/SAMBA_4_0/source/lib/events/events.h
   branches/SAMBA_4_0/source/lib/events/events_aio.c
   branches/SAMBA_4_0/source/lib/events/events_epoll.c
   branches/SAMBA_4_0/source/lib/events/events_internal.h
   branches/SAMBA_4_0/source/lib/events/events_liboop.c
   branches/SAMBA_4_0/source/lib/events/events_select.c
   branches/SAMBA_4_0/source/lib/events/events_standard.c


Changeset:
Modified: branches/SAMBA_4_0/source/lib/events/config.mk
===================================================================
--- branches/SAMBA_4_0/source/lib/events/config.mk	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/config.mk	2007-01-21 08:23:14 UTC (rev 20928)
@@ -31,7 +31,7 @@
 ##############################
 # Start SUBSYSTEM LIBEVENTS
 [SUBSYSTEM::LIBEVENTS]
-OBJ_FILES = events.o events_timed.o
+OBJ_FILES = events.o events_timed.o events_signal.o
 PUBLIC_DEPENDENCIES = LIBTALLOC
 # End SUBSYSTEM LIBEVENTS
 ##############################

Modified: branches/SAMBA_4_0/source/lib/events/events.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -240,6 +240,18 @@
 }
 
 /*
+  add a signal event
+  return NULL on failure
+*/
+struct timed_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
+				     int signum,
+				     event_signal_handler_t handler, 
+				     void *private_data)
+{
+	return ev->ops->add_signal(ev, mem_ctx, signum, handler, private_data);
+}
+
+/*
   do a single event loop using the events defined in ev 
 */
 _PUBLIC_ int event_loop_once(struct event_context *ev)

Modified: branches/SAMBA_4_0/source/lib/events/events.h
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events.h	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events.h	2007-01-21 08:23:14 UTC (rev 20928)
@@ -28,14 +28,17 @@
 struct fd_event;
 struct timed_event;
 struct aio_event;
+struct signal_event;
 
 /* event handler types */
 typedef void (*event_fd_handler_t)(struct event_context *, struct fd_event *, 
 				   uint16_t , void *);
 typedef void (*event_timed_handler_t)(struct event_context *, struct timed_event *, 
 				      struct timeval , void *);
+typedef void (*event_signal_handler_t)(struct event_context *, struct signal_event *, 
+				       int , int, void *);
 typedef void (*event_aio_handler_t)(struct event_context *, struct aio_event *, 
-				    int , void *);
+				    int, void *);
 
 struct event_context *event_context_init(TALLOC_CTX *mem_ctx);
 struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name);
@@ -50,6 +53,11 @@
 				    event_timed_handler_t handler, 
 				    void *private);
 
+struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
+				      int signum,
+				      event_signal_handler_t handler, 
+				      void *private);
+
 struct iocb;
 struct aio_event *event_add_aio(struct event_context *ev,
 				TALLOC_CTX *mem_ctx,

Modified: branches/SAMBA_4_0/source/lib/events/events_aio.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_aio.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_aio.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -225,6 +225,11 @@
 
 	if (aio_ev->epoll_fd == -1) return -1;
 
+	if (aio_ev->ev->num_signal_handlers && 
+	    common_event_check_signal(aio_ev->ev)) {
+		return 0;
+	}
+
 	if (tvalp) {
 		timeout.tv_sec = tvalp->tv_sec;
 		timeout.tv_nsec = tvalp->tv_usec;
@@ -236,7 +241,11 @@
 
 	ret = io_getevents(aio_ev->ioctx, 1, 8,
 			   events, tvalp?&timeout:NULL);
+
 	if (ret == -EINTR) {
+		if (aio_ev->ev->num_signal_handlers) {
+			common_event_check_signal(aio_ev->ev);
+		}
 		return 0;
 	}
 
@@ -488,6 +497,7 @@
 	.get_fd_flags	= aio_event_get_fd_flags,
 	.set_fd_flags	= aio_event_set_fd_flags,
 	.add_timed	= common_event_add_timed,
+	.add_signal	= common_event_add_signal,
 	.loop_once	= aio_event_loop_once,
 	.loop_wait	= aio_event_loop_wait,
 };

Modified: branches/SAMBA_4_0/source/lib/events/events_epoll.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_epoll.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_epoll.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -214,8 +214,19 @@
 		timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
 	}
 
+	if (epoll_ev->ev->num_signal_handlers && 
+	    common_event_check_signal(epoll_ev->ev)) {
+		return 0;
+	}
+
 	ret = epoll_wait(epoll_ev->epoll_fd, events, MAXEVENTS, timeout);
 
+	if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) {
+		if (common_event_check_signal(epoll_ev->ev)) {
+			return 0;
+		}
+	}
+
 	if (ret == -1 && errno != EINTR) {
 		epoll_fallback_to_select(epoll_ev, "epoll_wait() failed");
 		return -1;
@@ -397,6 +408,7 @@
 	.get_fd_flags	= epoll_event_get_fd_flags,
 	.set_fd_flags	= epoll_event_set_fd_flags,
 	.add_timed	= common_event_add_timed,
+	.add_signal	= common_event_add_signal,
 	.loop_once	= epoll_event_loop_once,
 	.loop_wait	= epoll_event_loop_wait,
 };

Modified: branches/SAMBA_4_0/source/lib/events/events_internal.h
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_internal.h	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_internal.h	2007-01-21 08:23:14 UTC (rev 20928)
@@ -47,6 +47,12 @@
 				     struct iocb *iocb, 
 				     event_aio_handler_t handler, 
 				     void *private_data);
+	/* signal functions */
+	struct signal_event *(*add_signal)(struct event_context *ev, 
+					   TALLOC_CTX *mem_ctx,
+					   int signum,
+					   event_signal_handler_t handler, 
+					   void *private_data);
 
 	/* loop functions */
 	int (*loop_once)(struct event_context *ev);
@@ -77,6 +83,14 @@
 	void *additional_data;
 };
 
+struct signal_event {
+	struct signal_event *prev, *next;
+	struct event_context *event_ctx;
+	event_signal_handler_t handler;
+	void *private_data;
+	int signum;
+};
+
 /* aio event is private to the aio backend */
 struct aio_event;
 
@@ -89,6 +103,12 @@
 
 	/* this is private for the events_ops implementation */
 	void *additional_data;
+
+	/* number of signal event handlers */
+	int num_signal_handlers;
+
+	/* pipe hack used with signal handlers */
+	struct fd_event *pipe_fde;
 };
 
 
@@ -98,3 +118,11 @@
 					   struct timeval, event_timed_handler_t, void *);
 void common_event_loop_timer(struct event_context *);
 struct timeval common_event_loop_delay(struct event_context *);
+
+struct signal_event *common_event_add_signal(struct event_context *ev, 
+					     TALLOC_CTX *mem_ctx,
+					     int signum,
+					     event_signal_handler_t handler, 
+					     void *private_data);
+int common_event_check_signal(struct event_context *ev);
+

Modified: branches/SAMBA_4_0/source/lib/events/events_liboop.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_liboop.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_liboop.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -274,6 +274,7 @@
 	.get_fd_flags	= oop_event_get_fd_flags,
 	.set_fd_flags	= oop_event_set_fd_flags,
 	.add_timed	= oop_event_add_timed,
+	.add_signal	= common_event_add_signal,
 	.loop_once	= oop_event_loop_once,
 	.loop_wait	= oop_event_loop_wait,
 };

Modified: branches/SAMBA_4_0/source/lib/events/events_select.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_select.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_select.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -197,8 +197,19 @@
 		}
 	}
 
+	if (select_ev->ev->num_signal_handlers && 
+	    common_event_check_signal(select_ev->ev)) {
+		return 0;
+	}
+
 	selrtn = select(select_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
 
+	if (selrtn == -1 && errno == EINTR && 
+	    select_ev->ev->num_signal_handlers) {
+		common_event_check_signal(select_ev->ev);
+		return 0;
+	}
+
 	if (selrtn == -1 && errno == EBADF) {
 		/* the socket is dead! this should never
 		   happen as the socket should have first been
@@ -279,6 +290,7 @@
 	.get_fd_flags	= select_event_get_fd_flags,
 	.set_fd_flags	= select_event_set_fd_flags,
 	.add_timed	= common_event_add_timed,
+	.add_signal	= common_event_add_signal,
 	.loop_once	= select_event_loop_once,
 	.loop_wait	= select_event_loop_wait,
 };

Added: branches/SAMBA_4_0/source/lib/events/events_signal.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_signal.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_signal.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -0,0 +1,153 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   common events code for signal events
+
+   Copyright (C) Andrew Tridgell	2007
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/filesys.h"
+#include "system/select.h"
+#include "lib/util/dlinklist.h"
+#include "lib/events/events.h"
+#include "lib/events/events_internal.h"
+
+#define NUM_SIGNALS 64
+
+/*
+  the poor design of signals means that this table must be static global
+*/
+static struct {
+	struct signal_event *sig_handlers[NUM_SIGNALS];
+	uint32_t signal_count[NUM_SIGNALS];
+	uint32_t got_signal;
+	int pipe_hack[2];
+} sig_state;
+
+
+/*
+  signal handler - redirects to registered signals
+*/
+static void signal_handler(int signum)
+{
+	char c = 0;
+	sig_state.signal_count[signum]++;
+	sig_state.got_signal++;
+	/* doesn't matter if this pipe overflows */
+	write(sig_state.pipe_hack[1], &c, 1);
+}
+
+
+/*
+  destroy a signal event
+*/
+static int signal_event_destructor(struct signal_event *se)
+{
+	se->event_ctx->num_signal_handlers--;
+	DLIST_REMOVE(sig_state.sig_handlers[se->signum], se);
+	if (sig_state.sig_handlers[se->signum] == NULL) {
+		signal(se->signum, SIG_DFL);
+	}
+	return 0;
+}
+
+/*
+  this is part of the pipe hack needed to avoid the signal race condition
+*/
+static void signal_pipe_handler(struct event_context *ev, struct fd_event *fde, 
+				uint16_t flags, void *private)
+{
+	char c[16];
+	/* its non-blocking, doesn't matter if we read too much */
+	read(sig_state.pipe_hack[0], c, sizeof(c));
+}
+
+/*
+  add a signal event
+  return NULL on failure (memory allocation error)
+*/
+struct signal_event *common_event_add_signal(struct event_context *ev, 
+					    TALLOC_CTX *mem_ctx,
+					    int signum,
+					    event_signal_handler_t handler, 
+					    void *private_data) 
+{
+	struct signal_event *se;
+
+	if (signum >= NUM_SIGNALS) {
+		return NULL;
+	}
+
+	se = talloc(mem_ctx?mem_ctx:ev, struct signal_event);
+	if (se == NULL) return NULL;
+
+	se->event_ctx		= ev;
+	se->handler		= handler;
+	se->private_data	= private_data;
+	se->signum              = signum;
+
+	if (sig_state.sig_handlers[signum] == NULL) {
+		signal(signum, signal_handler);
+	}
+
+	DLIST_ADD(sig_state.sig_handlers[signum], se);
+
+	talloc_set_destructor(se, signal_event_destructor);
+
+	if (ev->pipe_fde == NULL) {
+		if (sig_state.pipe_hack[0] == 0 && 
+		    sig_state.pipe_hack[1] == 0) {
+			pipe(sig_state.pipe_hack);
+			set_blocking(sig_state.pipe_hack[0], False);
+			set_blocking(sig_state.pipe_hack[1], False);
+		}
+		ev->pipe_fde = event_add_fd(ev, ev, sig_state.pipe_hack[0],
+					    EVENT_FD_READ, signal_pipe_handler, NULL);
+	}
+	ev->num_signal_handlers++;
+
+	return se;
+}
+
+
+/*
+  check if a signal is pending
+  return != 0 if a signal was pending
+*/
+int common_event_check_signal(struct event_context *ev)
+{
+	int i;
+	if (sig_state.got_signal == 0) {
+		return 0;
+	}
+	
+	for (i=0;i<NUM_SIGNALS+1;i++) {
+		uint32_t count = sig_state.signal_count[i];
+		if (count != 0) {
+			struct signal_event *se, *next;
+			for (se=sig_state.sig_handlers[i];se;se=next) {
+				next = se->next;
+				se->handler(ev, se, i, count, se->private_data);
+			}
+			sig_state.signal_count[i] -= count;
+			sig_state.got_signal -= count;
+		}
+	}
+
+	return 1;
+}

Modified: branches/SAMBA_4_0/source/lib/events/events_standard.c
===================================================================
--- branches/SAMBA_4_0/source/lib/events/events_standard.c	2007-01-20 23:53:17 UTC (rev 20927)
+++ branches/SAMBA_4_0/source/lib/events/events_standard.c	2007-01-21 08:23:14 UTC (rev 20928)
@@ -229,8 +229,19 @@
 		timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
 	}
 
+	if (epoll_ev->ev->num_signal_handlers && 
+	    common_event_check_signal(epoll_ev->ev)) {
+		return 0;
+	}
+
 	ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
 
+	if (ret == -1 && errno == EINTR && epoll_ev->ev->num_signal_handlers) {
+		if (common_event_check_signal(epoll_ev->ev)) {
+			return 0;
+		}
+	}
+
 	if (ret == -1 && errno != EINTR) {
 		epoll_fallback_to_select(std_ev, "epoll_wait() failed");
 		return -1;
@@ -434,8 +445,19 @@
 		}
 	}
 
+	if (std_ev->ev->num_signal_handlers && 
+	    common_event_check_signal(std_ev->ev)) {
+		return 0;
+	}
+
 	selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
 
+	if (selrtn == -1 && errno == EINTR && 
+	    std_ev->ev->num_signal_handlers) {
+		common_event_check_signal(std_ev->ev);
+		return 0;
+	}
+
 	if (selrtn == -1 && errno == EBADF) {
 		/* the socket is dead! this should never
 		   happen as the socket should have first been
@@ -520,6 +542,7 @@
 	.get_fd_flags	= std_event_get_fd_flags,
 	.set_fd_flags	= std_event_set_fd_flags,
 	.add_timed	= common_event_add_timed,
+	.add_signal	= common_event_add_signal,
 	.loop_once	= std_event_loop_once,
 	.loop_wait	= std_event_loop_wait,
 };



More information about the samba-cvs mailing list