From: Jaroslav Kysela Date: Tue, 3 Nov 2015 11:57:05 +0000 (+0100) Subject: epgdb: load - mmap - add SIGBUS recovery (when the file cannot be read), fixes #3238 X-Git-Tag: v4.2.1~1684 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d01071f67833c9ee93dafa436b26f8639a50c304;p=thirdparty%2Ftvheadend.git epgdb: load - mmap - add SIGBUS recovery (when the file cannot be read), fixes #3238 --- diff --git a/src/epgdb.c b/src/epgdb.c index f0a6b2f70..ad7b59089 100644 --- a/src/epgdb.c +++ b/src/epgdb.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "tvheadend.h" #include "queue.h" @@ -143,6 +145,16 @@ _epgdb_v2_process( char **sect, htsmsg_t *m, epggrab_stats_t *stats ) } } +/* + * Recovery + */ +static sigjmp_buf epg_mmap_env; + +static void epg_mmap_sigbus (int sig, siginfo_t *siginfo, void *ptr) +{ + siglongjmp(epg_mmap_env, 1); +} + /* * Load data */ @@ -154,6 +166,7 @@ void epg_init ( void ) uint8_t *mem, *rp; epggrab_stats_t stats; int ver = EPG_DB_VERSION; + struct sigaction act, oldact; char *sect = NULL; /* Find the right file (and version) */ @@ -168,6 +181,15 @@ void epg_init ( void ) tvhlog(LOG_DEBUG, "epgdb", "database does not exist"); return; } + + memset (&act, 0, sizeof(act)); + act.sa_sigaction = epg_mmap_sigbus; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGBUS, &act, &oldact)) { + tvhlog(LOG_ERR, "epgdb", "failed to install SIGBUS handler"); + close(fd); + return; + } /* Map file to memory */ if ( fstat(fd, &st) != 0 ) { @@ -185,6 +207,13 @@ void epg_init ( void ) goto end; } + if (sigsetjmp(epg_mmap_env, 1)) { + tvhlog(LOG_ERR, "epgdb", "failed to read from mapped file"); + if (mem) + munmap(mem, st.st_size); + goto end; + } + /* Process */ memset(&stats, 0, sizeof(stats)); while ( remain > 4 ) { @@ -245,6 +274,7 @@ void epg_init ( void ) /* Close file */ munmap(mem, st.st_size); end: + sigaction(SIGBUS, &oldact, NULL); close(fd); }