------------------------------------------------------------ revno: 346 committer: Razzloss <razzl...@gmail.com> branch nick: master timestamp: Thu 2010-01-07 21:49:29 +0200 message: Added SIGBUS handler for fastHash modified: Changelog.txt dcpp/HashManager.cpp
-- lp:linuxdcpp https://code.launchpad.net/~linuxdcpp-team/linuxdcpp/trunk Your team LinuxDC++ Team is subscribed to branch lp:linuxdcpp. To unsubscribe from this branch go to https://code.launchpad.net/~linuxdcpp-team/linuxdcpp/trunk/+edit-subscription.
=== modified file 'Changelog.txt' --- Changelog.txt 2010-01-01 00:57:24 +0000 +++ Changelog.txt 2010-01-07 19:49:29 +0000 @@ -40,6 +40,7 @@ [2009-11-02] Bumped minimum scons version to 0.98.1 to resolve multiple building issues. (Steven) [2009-11-25] Added issue with MacPorts boost lib not being detected on OS X to Readme. (thanks vszakats) [2009-12-31] lp#397365: Fixed sorting of "Time Left" column in transfers view. (Steven) +[2010-01-07] lp#473173: Crash when hashing files. Added missing SIGBUS handler. (Razzloss) *** 1.0.3 2009-02-01 *** [2008-08-10] lp#256236: Fixed a crash on startup when using auto-open options. === modified file 'dcpp/HashManager.cpp' --- dcpp/HashManager.cpp 2009-08-15 04:40:26 +0000 +++ dcpp/HashManager.cpp 2010-01-07 19:49:29 +0000 @@ -28,6 +28,8 @@ #ifndef _WIN32 #include <sys/mman.h> // mmap, munmap, madvise +#include <signal.h> // for handling read errors from previous trio +#include <setjmp.h> #endif namespace dcpp { @@ -600,6 +602,13 @@ #else // !_WIN32 static const int64_t BUF_SIZE = 0x1000000 - (0x1000000 % getpagesize()); +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); +} bool HashManager::Hasher::fastHash(const string& filename, uint8_t* , TigerTree& tth, int64_t size, CRC32Filter* xcrc32) { int fd = open(Text::fromUtf8(filename).c_str(), O_RDONLY); @@ -611,6 +620,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 +648,18 @@ return false; } + if (sigsetjmp(sb_env, 1)) { + if (buf != 0) { + munmap(buf, size_read); + } + if (sigaction(SIGBUS, &oldact, NULL) == -1) { + dcdebug("Failed to reset old signal handler for SIGBUS\n"); + } + + close(fd); + return false; + } + madvise(buf, size_read, MADV_SEQUENTIAL | MADV_WILLNEED); if(SETTING(MAX_HASH_SPEED) > 0) { @@ -656,6 +695,11 @@ size_left -= size_read; } close(fd); + + if (sigaction(SIGBUS, &oldact, NULL) == -1) { + dcdebug("Failed to reset old signal handler for SIGBUS\n"); + } + return true; }
_______________________________________________ Mailing list: https://launchpad.net/~linuxdcpp-team Post to : linuxdcpp-team@lists.launchpad.net Unsubscribe : https://launchpad.net/~linuxdcpp-team More help : https://help.launchpad.net/ListHelp