mirror of
https://github.com/mhx/dwarfs.git
synced 2025-08-04 10:16:34 -04:00
fix: make sure exceptions in worker threads produce an error message
This commit is contained in:
parent
179cfb8928
commit
0446513c06
@ -24,6 +24,8 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
#include <exception>
|
||||||
|
#include <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -326,7 +328,13 @@ class basic_worker_group final : public worker_group::impl, private Policy {
|
|||||||
::SetThreadPriority(hthr, THREAD_MODE_BACKGROUND_BEGIN);
|
::SetThreadPriority(hthr, THREAD_MODE_BACKGROUND_BEGIN);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
job();
|
try {
|
||||||
|
job();
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "FATAL ERROR: exception thrown in worker thread: "
|
||||||
|
<< folly::exceptionStr(std::current_exception()) << '\n';
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (is_background) {
|
if (is_background) {
|
||||||
::SetThreadPriority(hthr, THREAD_MODE_BACKGROUND_END);
|
::SetThreadPriority(hthr, THREAD_MODE_BACKGROUND_END);
|
||||||
|
@ -329,8 +329,11 @@ void os_access_mock::set_access_fail(fs::path const& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void os_access_mock::set_map_file_error(std::filesystem::path const& path,
|
void os_access_mock::set_map_file_error(std::filesystem::path const& path,
|
||||||
std::exception_ptr ep) {
|
std::exception_ptr ep,
|
||||||
map_file_err_[path] = std::move(ep);
|
size_t after_n_attempts) {
|
||||||
|
auto& e = map_file_errors_[path];
|
||||||
|
e.ep = std::move(ep);
|
||||||
|
e.remaining_successful_attempts = after_n_attempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t os_access_mock::size() const { return root_ ? root_->size() : 0; }
|
size_t os_access_mock::size() const { return root_ ? root_->size() : 0; }
|
||||||
@ -431,8 +434,16 @@ std::unique_ptr<mmif>
|
|||||||
os_access_mock::map_file(fs::path const& path, size_t size) const {
|
os_access_mock::map_file(fs::path const& path, size_t size) const {
|
||||||
if (auto de = find(path);
|
if (auto de = find(path);
|
||||||
de && de->status.type() == posix_file_type::regular) {
|
de && de->status.type() == posix_file_type::regular) {
|
||||||
if (auto it = map_file_err_.find(path); it != map_file_err_.end()) {
|
if (auto it = map_file_errors_.find(path); it != map_file_errors_.end()) {
|
||||||
std::rethrow_exception(it->second);
|
size_t remaining = 0;
|
||||||
|
do {
|
||||||
|
remaining = it->second.remaining_successful_attempts.load();
|
||||||
|
} while (remaining > 0 &&
|
||||||
|
!it->second.remaining_successful_attempts.compare_exchange_weak(
|
||||||
|
remaining, remaining - 1));
|
||||||
|
if (remaining == 0) {
|
||||||
|
std::rethrow_exception(it->second.ep);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_unique<mmap_mock>(
|
return std::make_unique<mmap_mock>(
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -92,8 +93,8 @@ class os_access_mock : public os_access {
|
|||||||
void add_local_files(std::filesystem::path const& path);
|
void add_local_files(std::filesystem::path const& path);
|
||||||
|
|
||||||
void set_access_fail(std::filesystem::path const& path);
|
void set_access_fail(std::filesystem::path const& path);
|
||||||
void
|
void set_map_file_error(std::filesystem::path const& path,
|
||||||
set_map_file_error(std::filesystem::path const& path, std::exception_ptr ep);
|
std::exception_ptr ep, size_t after_n_attempts = 0);
|
||||||
|
|
||||||
void setenv(std::string name, std::string value);
|
void setenv(std::string name, std::string value);
|
||||||
|
|
||||||
@ -119,6 +120,11 @@ class os_access_mock : public os_access {
|
|||||||
std::optional<std::string> getenv(std::string_view name) const override;
|
std::optional<std::string> getenv(std::string_view name) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct error_info {
|
||||||
|
std::exception_ptr ep{};
|
||||||
|
std::atomic<size_t> mutable remaining_successful_attempts{0};
|
||||||
|
};
|
||||||
|
|
||||||
static std::vector<std::string> splitpath(std::filesystem::path const& path);
|
static std::vector<std::string> splitpath(std::filesystem::path const& path);
|
||||||
struct mock_dirent* find(std::filesystem::path const& path) const;
|
struct mock_dirent* find(std::filesystem::path const& path) const;
|
||||||
struct mock_dirent* find(std::vector<std::string> parts) const;
|
struct mock_dirent* find(std::vector<std::string> parts) const;
|
||||||
@ -128,7 +134,7 @@ class os_access_mock : public os_access {
|
|||||||
std::unique_ptr<mock_dirent> root_;
|
std::unique_ptr<mock_dirent> root_;
|
||||||
size_t ino_{1000000};
|
size_t ino_{1000000};
|
||||||
std::set<std::filesystem::path> access_fail_set_;
|
std::set<std::filesystem::path> access_fail_set_;
|
||||||
std::map<std::filesystem::path, std::exception_ptr> map_file_err_;
|
std::map<std::filesystem::path, error_info> map_file_errors_;
|
||||||
std::map<std::string, std::string> env_;
|
std::map<std::string, std::string> env_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2114,3 +2114,16 @@ TEST(mkdwarfs_test, map_file_error) {
|
|||||||
::testing::HasSubstr("map_file_error, creating empty inode"));
|
::testing::HasSubstr("map_file_error, creating empty inode"));
|
||||||
EXPECT_THAT(t.err(), ::testing::HasSubstr("filesystem created with 1 error"));
|
EXPECT_THAT(t.err(), ::testing::HasSubstr("filesystem created with 1 error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: enable this once we know how to make it work reliably
|
||||||
|
#if 0
|
||||||
|
TEST(mkdwarfs_test, map_file_error_delayed) {
|
||||||
|
mkdwarfs_tester t;
|
||||||
|
t.os->set_map_file_error(
|
||||||
|
"/somedir/ipsum.py",
|
||||||
|
std::make_exception_ptr(std::runtime_error("map_file_error")), 1);
|
||||||
|
|
||||||
|
EXPECT_DEATH(t.run("-i / -o - --categorize --no-progress --log-level=error"),
|
||||||
|
"");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user