From 615456aae8c309d0e82c6b549d17a7109554a4f6 Mon Sep 17 00:00:00 2001 From: "Carsten Haitzler (Rasterman)" Date: Tue, 13 Jan 2015 19:26:55 +0900 Subject: [PATCH] eina - mmap safety handler - fix to only handle sigbus's from io @fix this fixes the eina mmap safety handler to only handle what comes from actual i/o errors (not actual corrupt/hw memory faults or invalid objects), and if it's not a sigbus eina mmap should handle then pass it onto the previous handler before eina mmap took over. --- src/lib/eina/eina_mmap.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/lib/eina/eina_mmap.c b/src/lib/eina/eina_mmap.c index 99a222a..42ac957 100644 --- a/src/lib/eina/eina_mmap.c +++ b/src/lib/eina/eina_mmap.c @@ -65,6 +65,7 @@ static Eina_Bool mmap_safe = EINA_FALSE; static int _eina_mmap_log_dom = -1; static int _eina_mmap_zero_fd = -1; static long _eina_mmap_pagesize = -1; +static struct sigaction _eina_mmap_prev_sigaction; #ifdef ERR #undef ERR @@ -77,9 +78,7 @@ static long _eina_mmap_pagesize = -1; #define DBG(...) EINA_LOG_DOM_DBG(_eina_mmap_log_dom, __VA_ARGS__) static void -_eina_mmap_safe_sigbus(int sig EINA_UNUSED, - siginfo_t *siginfo, - void *ptr EINA_UNUSED) +_eina_mmap_safe_sigbus(int sig, siginfo_t *siginfo, void *ptr) { unsigned char *addr = (unsigned char *)(siginfo->si_addr); int perrno; @@ -87,11 +86,41 @@ _eina_mmap_safe_sigbus(int sig EINA_UNUSED, /* save previous errno */ perrno = errno; /* if problems was an unaligned access - complain accordingly and abort */ - if (siginfo->si_code == BUS_ADRALN) + if (siginfo->si_code != BUS_ADRERR) { - ERR("Unaligned memory access. SIGBUS!!!"); + if (siginfo->si_code == BUS_ADRALN) + ERR("Unaligned memory access - BUS_ADRALN. SIGBUS!!!"); + else if (siginfo->si_code == BUS_OBJERR) + ERR("Invalid object - BUS_OBJERR. SIGBUS!!!"); + else if (siginfo->si_code == BUS_MCEERR_AR) + ERR("Memory Fault - BUS_MCEERR_AR. SIGBUS!!!"); + else if (siginfo->si_code == BUS_MCEERR_AO) + ERR("Memory Fault - BUS_MCEERR_AO. SIGBUS!!!"); errno = perrno; - abort(); + if (_eina_mmap_prev_sigaction.sa_flags & SA_SIGINFO) + { + if (_eina_mmap_prev_sigaction.sa_sigaction) + { + _eina_mmap_prev_sigaction.sa_sigaction(sig, siginfo, ptr); + if (_eina_mmap_prev_sigaction.sa_flags & SA_RESETHAND) + _eina_mmap_prev_sigaction.sa_sigaction = NULL; + if (_eina_mmap_prev_sigaction.sa_flags & SA_RESTART) + return; + } + abort(); + } + else + { + if (_eina_mmap_prev_sigaction.sa_handler == SIG_IGN) + return; + else if (_eina_mmap_prev_sigaction.sa_handler == SIG_DFL) + abort(); + else if (_eina_mmap_prev_sigaction.sa_handler) + { + _eina_mmap_prev_sigaction.sa_handler(sig); + abort(); + } + } } /* send this to stderr - not eina_log. Specifically want this on stderr */ fprintf(stderr, @@ -171,7 +200,7 @@ eina_mmap_safety_enabled_set(Eina_Bool enabled) sa.sa_sigaction = _eina_mmap_safe_sigbus; sa.sa_flags = SA_RESTART | SA_SIGINFO; sigemptyset(&sa.sa_mask); - if (sigaction(SIGBUS, &sa, NULL) == 0) goto done; + if (sigaction(SIGBUS, &sa, &_eina_mmap_prev_sigaction) == 0) goto done; /* setup of SIGBUS handler failed, lets close zero page dev and fail */ close(_eina_mmap_zero_fd); _eina_mmap_zero_fd = -1; -- 2.7.4