Skip to content

Commit 0e8a9eb

Browse files
authored
chore: improve diagnostics when thread creation fails (#14082)
This PR includes the OS-level failure messages in the crash message when thread creation fails. It also prevents some `std::function` objects being leaked in this failure case, and slightly cleans up some use of `unique_ptr`.
1 parent e695749 commit 0e8a9eb

1 file changed

Lines changed: 15 additions & 14 deletions

File tree

src/runtime/thread.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Leonardo de Moura
1919
#include "runtime/exception.h"
2020
#include "runtime/alloc.h"
2121
#include "runtime/stack_overflow.h"
22+
#include "runtime/sstream.h"
2223

2324
#ifndef LEAN_DEFAULT_THREAD_STACK_SIZE
2425
#ifdef LEAN_EMSCRIPTEN
@@ -61,12 +62,10 @@ extern "C" LEAN_EXPORT void lean_finalize_thread() {
6162

6263
static void thread_main(void * p) {
6364
lean_initialize_thread();
64-
std::unique_ptr<runnable> f;
65-
f.reset(reinterpret_cast<runnable *>(p));
66-
67-
(*f)();
68-
f.reset();
69-
65+
{
66+
std::unique_ptr<runnable> f(reinterpret_cast<runnable *>(p));
67+
(*f)();
68+
}
7069
lean_finalize_thread();
7170
}
7271

@@ -97,14 +96,15 @@ struct lthread::imp {
9796
}
9897

9998
imp(runnable const & p) {
100-
runnable * f = new std::function<void()>(mk_thread_proc(p, get_max_heartbeat()));
99+
std::unique_ptr<runnable> f = std::make_unique<runnable>(mk_thread_proc(p, get_max_heartbeat()));
101100
// Without `IS_A_RESERVATION`, `m_thread_stack_size` would be the initial *commit* size,
102101
// quickly exhausting the available address space with our large default stack size.
103102
m_thread = CreateThread(nullptr, m_thread_stack_size,
104-
_main, f, STACK_SIZE_PARAM_IS_A_RESERVATION, nullptr);
103+
_main, f.get(), STACK_SIZE_PARAM_IS_A_RESERVATION, nullptr);
105104
if (m_thread == NULL) {
106-
throw exception("failed to create thread");
105+
throw exception((sstream() << "failed to create thread: " << GetLastError()).str());
107106
}
107+
f.release(); // Now owned by thread_main
108108
}
109109

110110
~imp() {
@@ -132,13 +132,14 @@ struct lthread::imp {
132132

133133
imp(runnable const & p) {
134134
pthread_attr_init(&m_attr);
135-
if (pthread_attr_setstacksize(&m_attr, m_thread_stack_size)) {
136-
throw exception("failed to set thread stack size");
135+
if (int err = pthread_attr_setstacksize(&m_attr, m_thread_stack_size); err != 0) {
136+
throw exception((sstream() << "failed to set thread stack size: " << strerror(err)).str());
137137
}
138-
runnable * f = new std::function<void()>(mk_thread_proc(p, get_max_heartbeat()));
139-
if (pthread_create(&m_thread, &m_attr, _main, f)) {
140-
throw exception("failed to create thread");
138+
std::unique_ptr<runnable> f = std::make_unique<runnable>(mk_thread_proc(p, get_max_heartbeat()));
139+
if (int err = pthread_create(&m_thread, &m_attr, _main, f.get()); err != 0) {
140+
throw exception((sstream() << "failed to create thread: " << strerror(err)).str());
141141
}
142+
f.release(); // Now owned by thread_main
142143
}
143144

144145
~imp() {

0 commit comments

Comments
 (0)