=== modified file 'dcpp/HashManager.cpp' --- dcpp/HashManager.cpp 2009-08-15 04:40:26 +0000 +++ dcpp/HashManager.cpp 2009-11-04 18:25:02 +0000 @@ -28,6 +28,16 @@ #ifndef _WIN32 #include // mmap, munmap, madvise +#include // for handling read errors from previous trio +#include + +static sigjmp_buf sb_env; + +static void sigbus_handler(int signum, siginfo_t* info, void* context) { + // Jump back to the fastHash which will return error + if (signum == SIGBUS && (info->si_code == BUS_ADRERR || info->si_code == BUS_OBJERR)) // Apparently truncating file in Solaris sets si_code to BUS_OBJERR + siglongjmp(sb_env, 1); +} #endif namespace dcpp { @@ -611,6 +621,24 @@ int64_t size_read = 0; void *buf = 0; + // Prepare and setup a signal handler in case of SIGBUS during mmapped file reads. + // SIGBUS can be sent when the file is truncated or in case of read errors. + struct sigaction act, oldact; + sigset_t signalset; + + sigemptyset(&signalset); + + act.sa_handler = NULL; + act.sa_sigaction = sigbus_handler; + act.sa_mask = signalset; + act.sa_flags = SA_SIGINFO | SA_RESETHAND; + + if (sigaction(SIGBUS, &act, &oldact) == -1) { + dcdebug("Failed to set signal handler for fastHash\n"); + close(fd); + return false; // Better luck with the slow hash. + } + uint32_t lastRead = GET_TICK(); while(pos <= size) { if(size_left > 0) { @@ -621,6 +649,11 @@ return false; } + if (sigsetjmp(sb_env, 1)) { + close(fd); + return false; + } + madvise(buf, size_read, MADV_SEQUENTIAL | MADV_WILLNEED); if(SETTING(MAX_HASH_SPEED) > 0) { @@ -656,6 +689,9 @@ size_left -= size_read; } close(fd); + if (sigaction(SIGBUS, &oldact, NULL) == -1) { + dcdebug("Failed to reset old signal handler for SIGBUS\n"); + } return true; }