added SIGBUS handler
authorVladimir Nadvornik <nadvornik@suse.cz>
Thu, 29 Jan 2009 18:05:41 +0000 (18:05 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Thu, 29 Jan 2009 18:05:41 +0000 (18:05 +0000)
src/main.c

index 27f8612..961e914 100644 (file)
@@ -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 @@ void exit_program(void)
        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 @@ gint main(gint argc, gchar *argv[])
        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);