[PATCH] Send TERMINATING event to Framework upon crash

abdoulaye berthe berthe.ab
Wed Mar 18 10:40:05 PDT 2015


From: Abdoulaye Berthe <berthe.ab at gmail.com>

This sends a terminating event to Android Framework to report
wpa_supplicant crash. It is done by saving the initial crash handler
and regitering a new one. When a crash occurs, the new handler sends
a TERMINATE CTRL-EVENT to Android Framework and call the saved handler.
The TERMINATE CTRL-EVENT allows Android to detect supplicant crash.

Signed-off-by: Abdoulaye Berthe <abdoulaye.berthe at sonymobile.com>
---
 src/utils/eloop.c               | 67 +++++++++++++++++++++++++++++++++++++++++
 src/utils/eloop.h               | 19 ++++++++++++
 wpa_supplicant/wpa_supplicant.c | 23 ++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/src/utils/eloop.c b/src/utils/eloop.c
index 4a565eb..6e56737 100644
--- a/src/utils/eloop.c
+++ b/src/utils/eloop.c
@@ -30,6 +30,14 @@
 #include <sys/epoll.h>
 #endif /* CONFIG_ELOOP_EPOLL */
 
+#ifdef ANDROID
+struct eloop_saved_signal {
+	int signal;
+	void *signal_user_data;
+	signal_handler *handler;
+};
+#endif /* ANDROID */
+
 struct eloop_sock {
 	int sock;
 	void *eloop_data;
@@ -101,6 +109,10 @@ struct eloop_data {
 
 static struct eloop_data eloop;
 
+#ifdef ANDROID
+int saved_signal_count;
+struct eloop_saved_signal *saved_signals;
+#endif /* ANDROID */
 
 #ifdef WPA_TRACE
 
@@ -883,6 +895,34 @@ int eloop_register_signal_terminate(eloop_signal_handler handler,
 	return ret;
 }
 
+#ifdef ANDROID
+int eloop_register_signal_and_save_handler(int sig, void *handler, void *user_data)
+{
+	void (*pret)(int);
+	pret = signal(sig, handler);
+
+	if (pret != SIG_ERR) {
+		struct eloop_saved_signal *tmp;
+		tmp = os_realloc_array(saved_signals, saved_signal_count + 1,
+				       sizeof(struct eloop_saved_signal));
+		if (tmp == NULL) {
+			return -1;
+		}
+
+		tmp[saved_signal_count].signal = sig;
+		tmp[saved_signal_count].handler = (signal_handler *) pret;
+		tmp[saved_signal_count].signal_user_data = user_data;
+		saved_signal_count ++;
+		saved_signals = tmp;
+		wpa_printf(MSG_DEBUG, "eloop_register_signal_sig_segv_handler success");
+	} else {
+		wpa_printf(MSG_ERROR, "eloop_register_signal_sig_segv_handler failure");
+		return -1;
+	}
+
+	return 0;
+}
+#endif /* ANDROID */
 
 int eloop_register_signal_reconfig(eloop_signal_handler handler,
 				   void *user_data)
@@ -1058,6 +1098,9 @@ void eloop_destroy(void)
 	eloop_sock_table_destroy(&eloop.writers);
 	eloop_sock_table_destroy(&eloop.exceptions);
 	os_free(eloop.signals);
+#ifdef ANDROID
+	os_free(saved_signals);
+#endif /* ANDROID */
 
 #ifdef CONFIG_ELOOP_POLL
 	os_free(eloop.pollfds);
@@ -1111,3 +1154,27 @@ void eloop_wait_for_read_sock(int sock)
 #ifdef CONFIG_ELOOP_SELECT
 #undef CONFIG_ELOOP_SELECT
 #endif /* CONFIG_ELOOP_SELECT */
+
+#ifdef ANDROID
+void * eloop_get_saved_signal_user_data(int sig)
+{
+	int i;
+	for (i = 0; i < saved_signal_count; i++) {
+		if (saved_signals[i].signal == sig) {
+			return saved_signals[i].signal_user_data;
+		}
+	}
+	return NULL;
+}
+
+signal_handler * eloop_get_saved_signal_handler(int sig)
+{
+	int i;
+	for (i = 0; i < saved_signal_count; i++) {
+		if (saved_signals[i].signal == sig) {
+			return saved_signals[i].handler;
+		}
+	}
+	return NULL;
+}
+#endif /* ANDROID */
diff --git a/src/utils/eloop.h b/src/utils/eloop.h
index 07b8c0d..1a20bf7 100644
--- a/src/utils/eloop.h
+++ b/src/utils/eloop.h
@@ -65,6 +65,10 @@ typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx);
  */
 typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
 
+#ifdef ANDROID
+typedef void (*signal_handler)(int sig);
+#endif /* ANDROID */
+
 /**
  * eloop_init() - Initialize global event loop data
  * Returns: 0 on success, -1 on failure
@@ -312,6 +316,15 @@ int eloop_register_signal_terminate(eloop_signal_handler handler,
 int eloop_register_signal_reconfig(eloop_signal_handler handler,
 				   void *user_data);
 
+#ifdef ANDROID
+/*
+ * eloop_register_signal_and_save_handler - Save old handler and register a
+ * new handler for signal.
+ */
+int eloop_register_signal_and_save_handler(int sig, void *handler,
+					   void *user_data);
+#endif /* ANDROID */
+
 /**
  * eloop_run - Start the event loop
  *
@@ -356,4 +369,10 @@ int eloop_terminated(void);
  */
 void eloop_wait_for_read_sock(int sock);
 
+#ifdef ANDROID
+void * eloop_get_saved_signal_user_data(int sig);
+
+signal_handler * eloop_get_saved_signal_handler(int sig);
+#endif /* ANDROID */
+
 #endif /* ELOOP_H */
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 19fb890..29cfdd7 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -812,6 +812,25 @@ static void wpa_supplicant_terminate(int sig, void *signal_ctx)
 	wpa_supplicant_terminate_proc(global);
 }
 
+#ifdef ANDROID
+static void wpa_supplicant_process_crash_signal(int sig)
+{
+	/* Send terminating event to state machine and recall saved handler for crash report */
+	struct wpa_global *global;
+	struct wpa_supplicant *wpa_s;
+	global = (struct wpa_global *) eloop_get_saved_signal_user_data(sig);
+	if (global) {
+		wpa_s = global->ifaces;
+		wpa_dbg(wpa_s, MSG_DEBUG, "%s: sending WPA_EVENT_TERMINATING to ctrl socket", __func__);
+		wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
+	}
+
+	if (eloop_get_saved_signal_handler(sig) != NULL) {
+		(*eloop_get_saved_signal_handler(sig))(sig);
+	}
+}
+#endif /* ANDROID */
+
 
 void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
 {
@@ -4642,6 +4661,10 @@ int wpa_supplicant_run(struct wpa_global *global)
 
 	eloop_register_signal_terminate(wpa_supplicant_terminate, global);
 	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
+#ifdef ANDROID
+	eloop_register_signal_and_save_handler(SIGSEGV, wpa_supplicant_process_crash_signal,
+					       global);
+#endif /* ANDROID */
 
 	eloop_run();
 
-- 
2.3.3




More information about the Hostap mailing list