diff --git a/rblibtorrent/Makefile b/rblibtorrent/Makefile index 138721370..53d599e82 100644 --- a/rblibtorrent/Makefile +++ b/rblibtorrent/Makefile @@ -35,24 +35,6 @@ define Package/rblibtorrent/description full featured client, although it comes with a working example client. endef -TRY_SIGNAL_VERSION:=751a7e5a5be14892bcfdff1e63c653bcbf71cf39 -TRY_SIGNAL_FILE:=$(PKG_NAME)-try_signal-$(TRY_SIGNAL_VERSION).tar.xz -define Download/try_signal - VERSION:=$(TRY_SIGNAL_VERSION) - SUBDIR:=deps/try_signal - FILE:=$(TRY_SIGNAL_FILE) - URL:=https://github.com/arvidn/try_signal.git - MIRROR_HASH:=32a432e35e81c79f21c49744f00696c112e0deab45d15d91c61ceb63fe25a5f8 - PROTO:=git -endef - -$(eval $(call Download,try_signal)) - -define Build/Prepare - $(Build/Prepare/Default) - xzcat $(DL_DIR)/$(TRY_SIGNAL_FILE) | tar -C $(PKG_BUILD_DIR) $(TAR_OPTIONS) -endef - TARGET_CFLAGS += $(FPIC) -ffunction-sections -fdata-sections TARGET_LDFLAGS += -Wl,--gc-sections,--as-needed diff --git a/rblibtorrent/src/deps/try_signal/CMakeLists.txt b/rblibtorrent/src/deps/try_signal/CMakeLists.txt new file mode 100644 index 000000000..945cd6c8a --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 2.8.12) +project(try_signal) + +add_library(try_signal signal_error_code try_signal) +target_include_directories(try_signal PUBLIC .) + diff --git a/rblibtorrent/src/deps/try_signal/Jamfile b/rblibtorrent/src/deps/try_signal/Jamfile new file mode 100644 index 000000000..ec001a898 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/Jamfile @@ -0,0 +1,18 @@ +lib try_signal + : # sources + signal_error_code.cpp try_signal.cpp + : # requirements + : # default build + static + : # usage requirements + . + ; + +exe test : test.cpp : try_signal static ; +explicit test ; + +exe example : example.cpp : try_signal static ; +explicit example ; + +install stage_test : test : . ; + diff --git a/rblibtorrent/src/deps/try_signal/LICENSE b/rblibtorrent/src/deps/try_signal/LICENSE new file mode 100644 index 000000000..152302662 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/rblibtorrent/src/deps/try_signal/README.rst b/rblibtorrent/src/deps/try_signal/README.rst new file mode 100644 index 000000000..22cbe1841 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/README.rst @@ -0,0 +1,53 @@ +try_signal +========== + +.. image:: https://travis-ci.org/arvidn/try_signal.svg?branch=master + :target: https://travis-ci.org/arvidn/try_signal + +.. image:: https://ci.appveyor.com/api/projects/status/le8jjroaai8081f1?svg=true + :target: https://ci.appveyor.com/project/arvidn/try-signal/branch/master + +The ``try_signal`` library provide a way to turn signals into C++ exceptions. +This is especially useful when performing disk I/O via memory mapped files, +where I/O errors are reported as ``SIGBUS`` and ``SIGSEGV`` or as structured +exceptions on windows. + +The function ``try_signal`` takes a function object that will be executed once. +If the function causes a signal (or structured exception) to be raised, it will +throw a C++ exception. Note that RAII may not be relied upon within this function. +It may not rely on destructors being called. Stick to simple operations like +memcopy. + +Example:: + + #include + #include + #include + #include "try_signal.hpp" + #include + #include + #include + + int main() try + { + int fd = open("test_file", O_RDWR); + void* map = mmap(nullptr, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + std::vector buf(1024); + std::iota(buf.begin(), buf.end(), 0); + + // disk full or access after EOF are reported as exceptions + sig::try_signal([&]{ + std::memcpy(map, buf.data(), buf.size()); + }); + + munmap(map, 1024); + close(fd); + return 0; + } + catch (std::exception const& e) + { + fprintf(stderr, "exited with exception: %s\n", e.what()); + return 1; + } + diff --git a/rblibtorrent/src/deps/try_signal/appveyor.yml b/rblibtorrent/src/deps/try_signal/appveyor.yml new file mode 100644 index 000000000..a185535aa --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/appveyor.yml @@ -0,0 +1,50 @@ +version: "{build}" +branches: + only: + - master +os: Visual Studio 2015 +clone_depth: 1 +environment: + matrix: + - variant: debug + compiler: msvc-14.0 + model: 64 + - variant: debug + compiler: msvc-14.0 + model: 32 + - variant: release + compiler: msvc-14.0 + model: 64 + - variant: debug + compiler: gcc + model: 32 + - variant: debug + compiler: gcc + model: 64 + - variant: release + compiler: gcc + model: 32 + +install: +- set ROOT_DIRECTORY=%CD% +- set BOOST_ROOT=c:\Libraries\boost_1_67_0 +- set BOOST_BUILD_PATH=%BOOST_ROOT%\tools\build +- echo %BOOST_ROOT% +- echo %BOOST_BUILD_PATH% +- set PATH=%PATH%;%BOOST_BUILD_PATH%\src\engine\bin.ntx86 +- ps: '"using msvc : 14.0 ;`nusing gcc : : : -std=c++11 ;" | Set-Content $env:HOMEDRIVE\$env:HOMEPATH\user-config.jam' +- type %HOMEDRIVE%%HOMEPATH%\user-config.jam +- set PATH=c:\msys64\mingw32\bin;%PATH% +- g++ --version +- python --version +- echo %ROOT_DIRECTORY% +- cd %BOOST_BUILD_PATH%\src\engine +- build.bat >nul +- cd %ROOT_DIRECTORY% + +build_script: +# examples +- b2.exe warnings=all warnings-as-errors=on -j2 %compiler% address-model=%model% variant=%variant% stage_test + +test_script: +- test diff --git a/rblibtorrent/src/deps/try_signal/example.cpp b/rblibtorrent/src/deps/try_signal/example.cpp new file mode 100644 index 000000000..703b8178a --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/example.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include "try_signal.hpp" +#include +#include +#include + +int main() try +{ + int fd = open("test_file", O_RDWR); + void* map = mmap(nullptr, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + std::vector buf(1024); + std::iota(buf.begin(), buf.end(), 0); + + // disk full or access after EOF are reported as exceptions + sig::try_signal([&]{ + std::memcpy(map, buf.data(), buf.size()); + }); + + munmap(map, 1024); + close(fd); + return 0; +} +catch (std::exception const& e) +{ + fprintf(stderr, "exited with exception: %s\n", e.what()); + return 1; +} + diff --git a/rblibtorrent/src/deps/try_signal/project-root.jam b/rblibtorrent/src/deps/try_signal/project-root.jam new file mode 100644 index 000000000..e69de29bb diff --git a/rblibtorrent/src/deps/try_signal/signal_error_code.cpp b/rblibtorrent/src/deps/try_signal/signal_error_code.cpp new file mode 100644 index 000000000..ae016cf8d --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/signal_error_code.cpp @@ -0,0 +1,209 @@ +/* + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include + +#include "signal_error_code.hpp" + +namespace { + + struct signal_error_category : std::error_category + { + const char* name() const noexcept override + { return "signal"; } + std::string message(int ev) const noexcept override + { +#define SIGNAL_CASE(x) case sig::errors::error_code_enum:: x: return #x; + switch (ev) + { + SIGNAL_CASE(abort) + SIGNAL_CASE(alarm) + SIGNAL_CASE(arithmetic_exception) + SIGNAL_CASE(hangup) + SIGNAL_CASE(illegal) + SIGNAL_CASE(interrupt) + SIGNAL_CASE(kill) + SIGNAL_CASE(pipe) + SIGNAL_CASE(quit) + case sig::errors::error_code_enum::segmentation: return "segmentation fault"; + SIGNAL_CASE(terminate) + SIGNAL_CASE(user1) + SIGNAL_CASE(user2) + SIGNAL_CASE(child) + SIGNAL_CASE(cont) + SIGNAL_CASE(stop) + SIGNAL_CASE(terminal_stop) + SIGNAL_CASE(terminal_in) + SIGNAL_CASE(terminal_out) + SIGNAL_CASE(bus) +#ifdef SIGPOLL + SIGNAL_CASE(poll) +#endif + SIGNAL_CASE(profiler) + SIGNAL_CASE(system_call) + SIGNAL_CASE(trap) + SIGNAL_CASE(urgent_data) + SIGNAL_CASE(virtual_timer) + SIGNAL_CASE(cpu_limit) + SIGNAL_CASE(file_size_limit) + default: return "unknown"; + } +#undef SIGNAL_CASE + } + std::error_condition default_error_condition(int ev) const noexcept override + { return {ev, *this}; } + }; +} // anonymous namespace + +namespace sig { +namespace errors { + + std::error_code make_error_code(error_code_enum e) + { + return {e, sig_category()}; + } + + std::error_condition make_error_condition(error_code_enum e) + { + return {e, sig_category()}; + } + +} // namespace errors + +std::error_category& sig_category() +{ + static signal_error_category signal_category; + return signal_category; +} + +#ifdef _WIN32 + +namespace { + sig::errors::error_code_enum map_exception_code(int const ev) + { + switch (ev) + { + case seh_errors::error_code_enum::access_violation: + case seh_errors::error_code_enum::array_bounds_exceeded: + case seh_errors::error_code_enum::guard_page: + case seh_errors::error_code_enum::stack_overflow: + case seh_errors::error_code_enum::flt_stack_check: + case seh_errors::error_code_enum::in_page_error: + return sig::errors::segmentation; + case seh_errors::error_code_enum::breakpoint: + case seh_errors::error_code_enum::single_step: + return sig::errors::trap; + case seh_errors::error_code_enum::datatype_misalignment: + return sig::errors::bus; + case seh_errors::error_code_enum::flt_denormal_operand: + case seh_errors::error_code_enum::flt_divide_by_zero: + case seh_errors::error_code_enum::flt_inexact_result: + case seh_errors::error_code_enum::flt_invalid_operation: + case seh_errors::error_code_enum::flt_overflow: + case seh_errors::error_code_enum::flt_underflow: + case seh_errors::error_code_enum::int_divide_by_zero: + case seh_errors::error_code_enum::int_overflow: + return sig::errors::arithmetic_exception; + case seh_errors::error_code_enum::illegal_instruction: + case seh_errors::error_code_enum::invalid_disposition: + case seh_errors::error_code_enum::priv_instruction: + case seh_errors::error_code_enum::noncontinuable_exception: + case seh_errors::error_code_enum::status_unwind_consolidate: + return sig::errors::illegal; + case seh_errors::error_code_enum::invalid_handle: + return sig::errors::pipe; + default: + return sig::errors::illegal; + } + } + + struct seh_error_category : std::error_category + { + const char* name() const noexcept override + { return "SEH"; } + std::string message(int ev) const noexcept override + { +#define SIGNAL_CASE(x) case sig::seh_errors::error_code_enum:: x: return #x; + switch (ev) + { + SIGNAL_CASE(access_violation) + SIGNAL_CASE(array_bounds_exceeded) + SIGNAL_CASE(guard_page) + SIGNAL_CASE(stack_overflow) + SIGNAL_CASE(flt_stack_check) + SIGNAL_CASE(in_page_error) + SIGNAL_CASE(breakpoint) + SIGNAL_CASE(single_step) + SIGNAL_CASE(datatype_misalignment) + SIGNAL_CASE(flt_denormal_operand) + SIGNAL_CASE(flt_divide_by_zero) + SIGNAL_CASE(flt_inexact_result) + SIGNAL_CASE(flt_invalid_operation) + SIGNAL_CASE(flt_overflow) + SIGNAL_CASE(flt_underflow) + SIGNAL_CASE(int_divide_by_zero) + SIGNAL_CASE(int_overflow) + SIGNAL_CASE(illegal_instruction) + SIGNAL_CASE(invalid_disposition) + SIGNAL_CASE(priv_instruction) + SIGNAL_CASE(noncontinuable_exception) + SIGNAL_CASE(status_unwind_consolidate) + SIGNAL_CASE(invalid_handle) + default: return "unknown"; + } +#undef SIGNAL_CASE + } + std::error_condition default_error_condition(int ev) const noexcept override + { return std::error_condition(map_exception_code(ev), sig_category()); } + }; +} // anonymous namespace + +namespace seh_errors { + + std::error_code make_error_code(error_code_enum e) + { + return {static_cast(e), seh_category()}; + } + +} // namespace errors + +std::error_category& seh_category() +{ + static seh_error_category seh_category; + return seh_category; +} + +#endif + +} // namespace sig + diff --git a/rblibtorrent/src/deps/try_signal/signal_error_code.hpp b/rblibtorrent/src/deps/try_signal/signal_error_code.hpp new file mode 100644 index 000000000..91ea9478c --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/signal_error_code.hpp @@ -0,0 +1,162 @@ +/* + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef SIGNAL_ERROR_CODE_HPP_INCLUDED +#define SIGNAL_ERROR_CODE_HPP_INCLUDED + +#include +#include + +#ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#ifdef __GNUC__ +#include +#else +#include +#endif +#endif + +namespace sig { +namespace errors { + +#ifdef _WIN32 +#define SIG_ENUM(name, sig) name, +#else +#define SIG_ENUM(name, sig) name = sig, +#endif + + enum error_code_enum: int + { + SIG_ENUM(abort, SIGABRT) + SIG_ENUM(alarm, SIGALRM) + SIG_ENUM(arithmetic_exception, SIGFPE) + SIG_ENUM(hangup, SIGHUP) + SIG_ENUM(illegal, SIGILL) + SIG_ENUM(interrupt, SIGINT) + SIG_ENUM(kill, SIGKILL) + SIG_ENUM(pipe, SIGPIPE) + SIG_ENUM(quit, SIGQUIT) + SIG_ENUM(segmentation, SIGSEGV) + SIG_ENUM(terminate, SIGTERM) + SIG_ENUM(user1, SIGUSR1) + SIG_ENUM(user2, SIGUSR2) + SIG_ENUM(child, SIGCHLD) + SIG_ENUM(cont, SIGCONT) + SIG_ENUM(stop, SIGSTOP) + SIG_ENUM(terminal_stop, SIGTSTP) + SIG_ENUM(terminal_in, SIGTTIN) + SIG_ENUM(terminal_out, SIGTTOU) + SIG_ENUM(bus, SIGBUS) +#ifdef SIGPOLL + SIG_ENUM(poll, SIGPOLL) +#endif + SIG_ENUM(profiler, SIGPROF) + SIG_ENUM(system_call, SIGSYS) + SIG_ENUM(trap, SIGTRAP) + SIG_ENUM(urgent_data, SIGURG) + SIG_ENUM(virtual_timer, SIGVTALRM) + SIG_ENUM(cpu_limit, SIGXCPU) + SIG_ENUM(file_size_limit, SIGXFSZ) + }; + +#undef SIG_ENUM + + std::error_code make_error_code(error_code_enum e); + std::error_condition make_error_condition(error_code_enum e); + +} // namespace errors + +std::error_category& sig_category(); + +#ifdef _WIN32 +namespace seh_errors { + + // standard error codes are "int", the win32 exceptions are DWORD (i.e. + // unsigned int). We coerce them into int here for compatibility, and we're + // not concerned about their arithmetic + enum error_code_enum: int + { + access_violation = int(EXCEPTION_ACCESS_VIOLATION), + array_bounds_exceeded = int(EXCEPTION_ARRAY_BOUNDS_EXCEEDED), + guard_page = int(EXCEPTION_GUARD_PAGE), + stack_overflow = int(EXCEPTION_STACK_OVERFLOW), + flt_stack_check = int(EXCEPTION_FLT_STACK_CHECK), + in_page_error = int(EXCEPTION_IN_PAGE_ERROR), + breakpoint = int(EXCEPTION_BREAKPOINT), + single_step = int(EXCEPTION_SINGLE_STEP), + datatype_misalignment = int(EXCEPTION_DATATYPE_MISALIGNMENT), + flt_denormal_operand = int(EXCEPTION_FLT_DENORMAL_OPERAND), + flt_divide_by_zero = int(EXCEPTION_FLT_DIVIDE_BY_ZERO), + flt_inexact_result = int(EXCEPTION_FLT_INEXACT_RESULT), + flt_invalid_operation = int(EXCEPTION_FLT_INVALID_OPERATION), + flt_overflow = int(EXCEPTION_FLT_OVERFLOW), + flt_underflow = int(EXCEPTION_FLT_UNDERFLOW), + int_divide_by_zero = int(EXCEPTION_INT_DIVIDE_BY_ZERO), + int_overflow = int(EXCEPTION_INT_OVERFLOW), + illegal_instruction = int(EXCEPTION_ILLEGAL_INSTRUCTION), + invalid_disposition = int(EXCEPTION_INVALID_DISPOSITION), + priv_instruction = int(EXCEPTION_PRIV_INSTRUCTION), + noncontinuable_exception = int(EXCEPTION_NONCONTINUABLE_EXCEPTION), + status_unwind_consolidate = int(STATUS_UNWIND_CONSOLIDATE), + invalid_handle = int(EXCEPTION_INVALID_HANDLE), + }; + + std::error_code make_error_code(error_code_enum e); +} + +std::error_category& seh_category(); + +#endif // _WIN32 + +} // namespace sig + +namespace std +{ +template<> +struct is_error_code_enum : std::true_type {}; + +template<> +struct is_error_condition_enum : std::true_type {}; + +#ifdef _WIN32 +template<> +struct is_error_code_enum : std::true_type {}; +#endif + +} // namespace std + +#endif + diff --git a/rblibtorrent/src/deps/try_signal/test.cpp b/rblibtorrent/src/deps/try_signal/test.cpp new file mode 100644 index 000000000..b8c67c8ee --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/test.cpp @@ -0,0 +1,47 @@ +#include +#include +#include // for memcpy + +#include "try_signal.hpp" + +int main() +{ + char const buf[] = "test...test"; + char dest[sizeof(buf)]; + + { + sig::try_signal([&]{ + std::memcpy(dest, buf, sizeof(buf)); + }); + if (!std::equal(buf, buf + sizeof(buf), dest)) { + fprintf(stderr, "ERROR: buffer not copied correctly\n"); + return 1; + } + } + + try { + void* invalid_pointer = nullptr; + sig::try_signal([&]{ + std::memcpy(dest, buf, sizeof(buf)); + std::memcpy(dest, invalid_pointer, sizeof(buf)); + }); + } + catch (std::system_error const& e) + { + if (e.code() != std::error_condition(sig::errors::segmentation)) { + fprintf(stderr, "ERROR: expected segmentaiton violation error\n"); + } + else { + fprintf(stderr, "OK\n"); + } + fprintf(stderr, "exited with expected system_error exception: %s\n", e.what()); + + // we expect this to happen, so return 0 + return e.code() == std::error_condition(sig::errors::segmentation) ? 0 : 1; + } + + // return non-zero here because we don't expect this + fprintf(stderr, "ERROR: expected exit through exception\n"); + return 1; +} + diff --git a/rblibtorrent/src/deps/try_signal/try_signal.cpp b/rblibtorrent/src/deps/try_signal/try_signal.cpp new file mode 100644 index 000000000..be5cd8d2b --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/try_signal.cpp @@ -0,0 +1,144 @@ +/* + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include +#include +#include +#include +#include + +#include "try_signal.hpp" + +#if !defined _WIN32 +// linux + +namespace sig { +namespace detail { + +namespace { +thread_local sigjmp_buf* jmpbuf = nullptr; +} + +std::atomic_flag once = ATOMIC_FLAG_INIT; + +scoped_jmpbuf::scoped_jmpbuf(sigjmp_buf* ptr) +{ + _previous_ptr = jmpbuf; + jmpbuf = ptr; + std::atomic_signal_fence(std::memory_order_release); +} + +scoped_jmpbuf::~scoped_jmpbuf() { jmpbuf = _previous_ptr; } + +void handler(int const signo, siginfo_t*, void*) +{ + std::atomic_signal_fence(std::memory_order_acquire); + if (jmpbuf) + siglongjmp(*jmpbuf, signo); + + // this signal was not caused within the scope of a try_signal object, + // invoke the default handler + signal(signo, SIG_DFL); + raise(signo); +} + +void setup_handler() +{ + struct sigaction sa; + sa.sa_sigaction = &sig::detail::handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &sa, nullptr); + sigaction(SIGBUS, &sa, nullptr); +} + +} // detail namespace +} // sig namespace + +#elif __GNUC__ +// mingw + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +namespace sig { +namespace detail { + +thread_local jmp_buf* jmpbuf = nullptr; + +long CALLBACK handler(EXCEPTION_POINTERS* pointers) +{ + std::atomic_signal_fence(std::memory_order_acquire); + if (jmpbuf) + longjmp(*jmpbuf, pointers->ExceptionRecord->ExceptionCode); + return EXCEPTION_CONTINUE_SEARCH; +} + +scoped_handler::scoped_handler(jmp_buf* ptr) +{ + _previous_ptr = jmpbuf; + jmpbuf = ptr; + std::atomic_signal_fence(std::memory_order_release); + _handle = AddVectoredExceptionHandler(1, sig::detail::handler); +} +scoped_handler::~scoped_handler() +{ + RemoveVectoredExceptionHandler(_handle); + jmpbuf = _previous_ptr; +} + +} // detail namespace +} // sig namespace + +#else +// windows + +#include // for EXCEPTION_* + +namespace sig { +namespace detail { + + // these are the kinds of SEH exceptions we'll translate into C++ exceptions + bool catch_error(int const code) + { + return code == EXCEPTION_IN_PAGE_ERROR + || code == EXCEPTION_ACCESS_VIOLATION + || code == EXCEPTION_ARRAY_BOUNDS_EXCEEDED; + } +} // detail namespace +} // namespace sig + +#endif // _WIN32 + + diff --git a/rblibtorrent/src/deps/try_signal/try_signal.hpp b/rblibtorrent/src/deps/try_signal/try_signal.hpp new file mode 100644 index 000000000..557d92bb6 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/try_signal.hpp @@ -0,0 +1,49 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRY_SIGNAL_HPP_INCLUDED +#define TRY_SIGNAL_HPP_INCLUDED + +#if !defined _WIN32 +// linux +#include "try_signal_posix.hpp" +#elif __GNUC__ +// mingw +#include "try_signal_mingw.hpp" +#else +// windows +#include "try_signal_msvc.hpp" +#endif + + +#endif // TRY_SIGNAL_HPP_INCLUDED + diff --git a/rblibtorrent/src/deps/try_signal/try_signal_mingw.hpp b/rblibtorrent/src/deps/try_signal/try_signal_mingw.hpp new file mode 100644 index 000000000..e4db043e2 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/try_signal_mingw.hpp @@ -0,0 +1,78 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRY_SIGNAL_MINGW_HPP_INCLUDED +#define TRY_SIGNAL_MINGW_HPP_INCLUDED + +#include "signal_error_code.hpp" + +#include // for jmp_buf + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +namespace sig { +namespace detail { + +struct scoped_handler +{ + scoped_handler(jmp_buf* ptr); + ~scoped_handler(); + scoped_handler(scoped_handler const&) = delete; + scoped_handler& operator=(scoped_handler const&) = delete; +private: + void* _handle; + jmp_buf* _previous_ptr; +}; + +} // detail namespace + +template +void try_signal(Fun&& f) +{ + jmp_buf buf; + int const code = setjmp(buf); + // set the thread local jmpbuf pointer, and make sure it's cleared when we + // leave the scope + sig::detail::scoped_handler scope(&buf); + if (code != 0) + throw std::system_error(std::error_code(code, seh_category())); + + f(); +} + +} // sig namespace + +#endif + diff --git a/rblibtorrent/src/deps/try_signal/try_signal_msvc.hpp b/rblibtorrent/src/deps/try_signal/try_signal_msvc.hpp new file mode 100644 index 000000000..04cc62df5 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/try_signal_msvc.hpp @@ -0,0 +1,61 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRY_SIGNAL_MSVC_HPP_INCLUDED +#define TRY_SIGNAL_MSVC_HPP_INCLUDED + +#include "signal_error_code.hpp" + +namespace sig { +namespace detail { + +bool catch_error(int const code); + +} // detail namespace + +template +void try_signal(Fun&& f) +{ + __try + { + f(); + } + __except (detail::catch_error(GetExceptionCode())) + { + throw std::system_error(std::error_code(GetExceptionCode(), seh_category())); + } +} + +} // sig namespace + +#endif + diff --git a/rblibtorrent/src/deps/try_signal/try_signal_posix.hpp b/rblibtorrent/src/deps/try_signal/try_signal_posix.hpp new file mode 100644 index 000000000..2c4615de4 --- /dev/null +++ b/rblibtorrent/src/deps/try_signal/try_signal_posix.hpp @@ -0,0 +1,82 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TRY_SIGNAL_POSIX_HPP_INCLUDED +#define TRY_SIGNAL_POSIX_HPP_INCLUDED + +#include "signal_error_code.hpp" +#include // for sigjmp_buf +#include + +namespace sig { + +namespace detail { + +extern std::atomic_flag once; + +struct scoped_jmpbuf +{ + explicit scoped_jmpbuf(sigjmp_buf* ptr); + ~scoped_jmpbuf(); + scoped_jmpbuf(scoped_jmpbuf const&) = delete; + scoped_jmpbuf& operator=(scoped_jmpbuf const&) = delete; +private: + sigjmp_buf* _previous_ptr; +}; + +void handler(int const signo, siginfo_t* si, void*); +void setup_handler(); + +} // detail namespace + +template +void try_signal(Fun&& f) +{ + if (sig::detail::once.test_and_set() == false) { + sig::detail::setup_handler(); + } + + sigjmp_buf buf; + int const sig = sigsetjmp(buf, 1); + // set the thread local jmpbuf pointer, and make sure it's cleared when we + // leave the scope + sig::detail::scoped_jmpbuf scope(&buf); + if (sig != 0) + throw std::system_error(static_cast(sig)); + + f(); +} + +} + +#endif +