Skip to content

Commit 1d92d89

Browse files
committed
util: Get rid of uncaught exceptions thrown by SignalInterrupt class
Replace exceptions thrown by signal and wait methods with [[nodiscard]] return values. This is mostly a refactoring, but there is a slight change of behavior if AbortShutdown function fails. The original behavior which was unintentionally changed in #27861 is restored, so it now triggers an assert failure again instead of throwing an exception. (The AbortShutdown function is only ever called in the the GUI version of Bitcoin Core when corruption is detected on loading and the user tries to reindex.) Problems with using exceptions were pointed out by MarcoFalke in bitcoin/bitcoin#27861 (comment).
1 parent ba93966 commit 1d92d89

File tree

3 files changed

+18
-16
lines changed

3 files changed

+18
-16
lines changed

src/shutdown.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@
1515

1616
void StartShutdown()
1717
{
18-
try {
19-
Assert(kernel::g_context)->interrupt();
20-
} catch (const std::system_error&) {
18+
if (!Assert(kernel::g_context)->interrupt()) {
2119
LogPrintf("Sending shutdown token failed\n");
2220
assert(0);
2321
}
2422
}
2523

2624
void AbortShutdown()
2725
{
28-
Assert(kernel::g_context)->interrupt.reset();
26+
if (!Assert(kernel::g_context)->interrupt.reset()) {
27+
LogPrintf("Reading shutdown token failed\n");
28+
assert(0);
29+
}
2930
}
3031

3132
bool ShutdownRequested()
@@ -35,9 +36,7 @@ bool ShutdownRequested()
3536

3637
void WaitForShutdown()
3738
{
38-
try {
39-
Assert(kernel::g_context)->interrupt.wait();
40-
} catch (const std::system_error&) {
39+
if (!Assert(kernel::g_context)->interrupt.wait()) {
4140
LogPrintf("Reading shutdown token failed\n");
4241
assert(0);
4342
}

src/util/signalinterrupt.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@ SignalInterrupt::operator bool() const
3030
return m_flag;
3131
}
3232

33-
void SignalInterrupt::reset()
33+
bool SignalInterrupt::reset()
3434
{
3535
// Cancel existing interrupt by waiting for it, this will reset condition flags and remove
3636
// the token from the pipe.
37-
if (*this) wait();
37+
if (*this && !wait()) return false;
3838
m_flag = false;
39+
return true;
3940
}
4041

41-
void SignalInterrupt::operator()()
42+
bool SignalInterrupt::operator()()
4243
{
4344
#ifdef WIN32
4445
std::unique_lock<std::mutex> lk(m_mutex);
@@ -52,23 +53,25 @@ void SignalInterrupt::operator()()
5253
// Write an arbitrary byte to the write end of the pipe.
5354
int res = m_pipe_w.TokenWrite('x');
5455
if (res != 0) {
55-
throw std::ios_base::failure("Could not write interrupt token");
56+
return false;
5657
}
5758
}
5859
#endif
60+
return true;
5961
}
6062

61-
void SignalInterrupt::wait()
63+
bool SignalInterrupt::wait()
6264
{
6365
#ifdef WIN32
6466
std::unique_lock<std::mutex> lk(m_mutex);
6567
m_cv.wait(lk, [this] { return m_flag.load(); });
6668
#else
6769
int res = m_pipe_r.TokenRead();
6870
if (res != 'x') {
69-
throw std::ios_base::failure("Did not read expected interrupt token");
71+
return false;
7072
}
7173
#endif
74+
return true;
7275
}
7376

7477
} // namespace util

src/util/signalinterrupt.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class SignalInterrupt
3030
public:
3131
SignalInterrupt();
3232
explicit operator bool() const;
33-
void operator()();
34-
void reset();
35-
void wait();
33+
[[nodiscard]] bool operator()();
34+
[[nodiscard]] bool reset();
35+
[[nodiscard]] bool wait();
3636

3737
private:
3838
std::atomic<bool> m_flag;

0 commit comments

Comments
 (0)