linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #00376
[Branch ~linuxdcpp-team/linuxdcpp/trunk] Rev 346: Added SIGBUS handler for fastHash
------------------------------------------------------------
revno: 346
committer: Razzloss <razzloss@xxxxxxxxx>
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;
}