changeset 1266:1267d17986f3

added SIGBUS handler
author nadvornik
date Thu, 29 Jan 2009 18:05:41 +0000
parents 0b94f0e6e3d0
children dfa378900ec9
files src/main.c
diffstat 1 files changed, 37 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/main.c	Mon Jan 26 21:08:05 2009 +0000
+++ b/src/main.c	Thu Jan 29 18:05:41 2009 +0000
@@ -34,6 +34,8 @@
 
 #include <gdk/gdkkeysyms.h> /* for keyboard values */
 
+#include <signal.h>
+#include <sys/mman.h>
 
 #include <math.h>
 #ifdef G_OS_UNIX
@@ -661,6 +663,39 @@
 	exit_program_final();
 }
 
+
+
+/* This code is supposed to handle situation when a file mmaped by image_loader 
+ * or by exif loader is truncated by some other process.
+ * This is probably not completely correct according to posix, because
+ * mmap is not in the list of calls that can be used safely in signal handler,
+ * but anyway, the handler is called in situation when the application would
+ * crash otherwise.
+ * Ideas for improvement are welcome ;)
+ */
+/* FIXME: this probably needs some better ifdefs. Please report any compilation problems */
+
+#ifdef SIGBUS
+static void sigbus_handler_cb(int signum, siginfo_t *info, void *context)
+{
+	unsigned long pagesize = sysconf(_SC_PAGE_SIZE);
+	DEBUG_1("SIGBUS %p", info->si_addr);
+	mmap((void *)(((unsigned long)info->si_addr / pagesize) * pagesize), pagesize, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+}
+#endif
+
+static void setup_sigbus_handler(void)
+{
+#ifdef SIGBUS
+	struct sigaction sigbus_action;
+	sigfillset(&sigbus_action.sa_mask);
+	sigbus_action.sa_sigaction = sigbus_handler_cb;
+	sigbus_action.sa_flags = SA_SIGINFO;
+
+	sigaction(SIGBUS, &sigbus_action, NULL);
+#endif
+}
+
 gint main(gint argc, gchar *argv[])
 {
 	LayoutWindow *lw;
@@ -699,6 +734,8 @@
 	log_printf("%s %s, This is an alpha release.\n", GQ_APPNAME, VERSION);
 #endif
 
+	setup_sigbus_handler();
+
 	/* register global notify functions */
 	file_data_register_notify_func(cache_notify_cb, NULL, NOTIFY_PRIORITY_HIGH);
 	file_data_register_notify_func(thumb_notify_cb, NULL, NOTIFY_PRIORITY_HIGH);