Kaynağa Gözat

faux.eloop: Can add signals on the fly

Serj Kalichev 3 yıl önce
ebeveyn
işleme
b0aa974ce5
3 değiştirilmiş dosya ile 52 ekleme ve 18 silme
  1. 4 3
      faux/eloop.h
  2. 37 8
      faux/eloop/eloop.c
  3. 11 7
      faux/eloop/private.h

+ 4 - 3
faux/eloop.h

@@ -16,9 +16,6 @@ typedef enum {
 	FAUX_ELOOP_FD = 3
 } faux_eloop_type_e;
 
-typedef bool_t faux_eloop_cb_f(faux_eloop_t *eloop, faux_eloop_type_e type,
-	void *associated_data, void *user_data);
-
 typedef struct {
 	int ev_id;
 } faux_eloop_info_sched_t;
@@ -32,6 +29,10 @@ typedef struct {
 	int signo;
 } faux_eloop_info_signal_t;
 
+// Callback function prototype
+typedef bool_t faux_eloop_cb_f(faux_eloop_t *eloop, faux_eloop_type_e type,
+	void *associated_data, void *user_data);
+
 
 C_DECL_BEGIN
 

+ 37 - 8
faux/eloop/eloop.c

@@ -29,6 +29,9 @@
 
 #include "private.h"
 
+#ifdef HAVE_SIGNALFD
+#define SIGNALFD_FLAGS (SFD_NONBLOCK | SFD_CLOEXEC)
+#endif
 
 static int faux_eloop_sched_compare(const void *first, const void *second)
 {
@@ -94,6 +97,7 @@ faux_eloop_t *faux_eloop_new(faux_eloop_cb_f *default_event_cb)
 		return NULL;
 
 	// Init
+	eloop->working = BOOL_FALSE;
 	eloop->default_event_cb = default_event_cb;
 
 	// Sched
@@ -115,6 +119,9 @@ faux_eloop_t *faux_eloop_new(faux_eloop_cb_f *default_event_cb)
 		faux_eloop_signal_compare, faux_eloop_signal_kcompare, faux_free);
 	assert(eloop->signals);
 	sigemptyset(&eloop->sig_set);
+#ifdef HAVE_SIGNALFD
+	eloop->signal_fd = -1;
+#endif
 
 	return eloop;
 }
@@ -142,9 +149,11 @@ bool_t faux_eloop_loop(faux_eloop_t *eloop)
 	sigset_t blocked_signals;
 	sigset_t orig_sig_set;
 
-#ifdef HAVE_SIGNALFD
-	int signal_fd = -1;
-#endif
+	// If event loop is active already and we try to start nested loop
+	// then return.
+	if (eloop->working)
+		return BOOL_FALSE;
+	eloop->working = BOOL_TRUE;
 
 	// Block signals to prevent race conditions while loop and ppoll()
 	// Catch signals while ppoll() only
@@ -154,8 +163,9 @@ bool_t faux_eloop_loop(faux_eloop_t *eloop)
 #ifdef HAVE_SIGNALFD
 	// Create Linux-specific signal file descriptor. Wait for all signals.
 	// Unneeded signals will be filtered out later.
-	signal_fd = signalfd(-1, &blocked_signals, SFD_NONBLOCK | SFD_CLOEXEC);
-	faux_pollfd_add(eloop->pollfds, signal_fd, POLLIN);
+	eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
+		SIGNALFD_FLAGS);
+	faux_pollfd_add(eloop->pollfds, eloop->signal_fd, POLLIN);
 #endif
 
 /*
@@ -259,7 +269,7 @@ printf("Sheduled event\n");
 
 #ifdef HAVE_SIGNALFD
 			// Read special signal file descriptor
-			if (fd == signal_fd) {
+			if (fd == eloop->signal_fd) {
 				struct signalfd_siginfo signal_info = {};
 
 				while (faux_read_block(fd, &signal_info,
@@ -313,13 +323,16 @@ printf("Sheduled event\n");
 
 #ifdef HAVE_SIGNALFD
 	// Close signal file descriptor
-	faux_pollfd_del_by_fd(eloop->pollfds, signal_fd);
-	close(signal_fd);
+	faux_pollfd_del_by_fd(eloop->pollfds, eloop->signal_fd);
+	close(eloop->signal_fd);
+	eloop->signal_fd = -1;
 #endif
 
 	// Unblock signals
 	sigprocmask(SIG_SETMASK, &orig_sig_set, NULL);
 
+	// Deactivate loop flag
+	eloop->working = BOOL_FALSE;
 
 	return retval;
 }
@@ -403,6 +416,14 @@ bool_t faux_eloop_add_signal(faux_eloop_t *eloop, int signo,
 		return BOOL_FALSE;
 	}
 
+	if (eloop->working) { // Add signal on the fly
+#ifdef HAVE_SIGNALFD
+		// Reattach signalfd handler with updated sig_set
+		eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
+			SIGNALFD_FLAGS);
+#endif
+	}
+
 	return BOOL_TRUE;
 }
 
@@ -418,5 +439,13 @@ bool_t faux_eloop_del_signal(faux_eloop_t *eloop, int signo)
 	sigdelset(&eloop->sig_set, signo);
 	faux_list_kdel(eloop->signals, &signo);
 
+	if (eloop->working) { // Add signal on the fly
+#ifdef HAVE_SIGNALFD
+		// Reattach signalfd handler with updated sig_set
+		eloop->signal_fd = signalfd(eloop->signal_fd, &eloop->sig_set,
+			SIGNALFD_FLAGS);
+#endif
+	}
+
 	return BOOL_TRUE;
 }

+ 11 - 7
faux/eloop/private.h

@@ -6,13 +6,17 @@
 
 
 struct faux_eloop_s {
-	faux_eloop_cb_f *default_event_cb;
-	faux_list_t *scheds;
-	faux_sched_t *faux_sched;
-	faux_list_t *fds;
-	faux_pollfd_t *pollfds;
-	faux_list_t *signals;
-	sigset_t sig_set;
+	bool_t working; // Is event loop active now. Can detect nested loop.
+	faux_eloop_cb_f *default_event_cb; // Default callback function
+	faux_list_t *scheds; // List of registered sched events
+	faux_sched_t *faux_sched; // Service shed structure
+	faux_list_t *fds; // List of registered file descriptors
+	faux_pollfd_t *pollfds; // Service object for ppoll()
+	faux_list_t *signals; // List of registered signals
+	sigset_t sig_set; // Mask of registered signals
+#ifdef HAVE_SIGNALFD
+	int signal_fd; // Handler for signalfd(). Valid when loop is active only
+#endif
 };