Skip to content

Commit cdc038c

Browse files
orangemochatjfontaine
authored andcommitted
vm: fix race condition in timeout
Eliminate a race condition between uv_async_send and the closing of the corresponding handle. Also made errors in Watchdog constructor call abort() Fixes nodejs#6088
1 parent 95ee84f commit cdc038c

File tree

2 files changed

+16
-24
lines changed

2 files changed

+16
-24
lines changed

src/node_watchdog.cc

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,34 +20,29 @@
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
#include "node_watchdog.h"
23+
#include "util.h"
2324
#include <assert.h>
2425

2526
namespace node {
2627

2728
using v8::V8;
2829

2930

30-
Watchdog::Watchdog(uint64_t ms) : thread_created_(false), destroyed_(false) {
31+
Watchdog::Watchdog(uint64_t ms) : destroyed_(false) {
3132
loop_ = uv_loop_new();
32-
if (!loop_)
33-
return;
33+
CHECK(loop_);
3434

3535
int rc = uv_async_init(loop_, &async_, &Watchdog::Async);
36-
assert(rc == 0);
36+
CHECK(0 == rc); // NOLINT(readability/check)
3737

3838
rc = uv_timer_init(loop_, &timer_);
39-
assert(rc == 0);
39+
CHECK(0 == rc); // NOLINT(readability/check)
4040

4141
rc = uv_timer_start(&timer_, &Watchdog::Timer, ms, 0);
42-
if (rc) {
43-
return;
44-
}
42+
CHECK(0 == rc); // NOLINT(readability/check)
4543

4644
rc = uv_thread_create(&thread_, &Watchdog::Run, this);
47-
if (rc) {
48-
return;
49-
}
50-
thread_created_ = true;
45+
CHECK(0 == rc); // NOLINT(readability/check)
5146
}
5247

5348

@@ -66,14 +61,15 @@ void Watchdog::Destroy() {
6661
return;
6762
}
6863

69-
if (thread_created_) {
70-
uv_async_send(&async_);
71-
uv_thread_join(&thread_);
72-
}
64+
uv_async_send(&async_);
65+
uv_thread_join(&thread_);
7366

74-
if (loop_) {
75-
uv_loop_delete(loop_);
76-
}
67+
uv_close(reinterpret_cast<uv_handle_t*>(&async_), NULL);
68+
69+
// UV_RUN_DEFAULT so that libuv has a chance to clean up.
70+
uv_run(loop_, UV_RUN_DEFAULT);
71+
72+
uv_loop_delete(loop_);
7773

7874
destroyed_ = true;
7975
}
@@ -86,11 +82,8 @@ void Watchdog::Run(void* arg) {
8682
uv_run(wd->loop_, UV_RUN_ONCE);
8783

8884
// Loop ref count reaches zero when both handles are closed.
89-
uv_close(reinterpret_cast<uv_handle_t*>(&wd->async_), NULL);
85+
// Close the timer handle on this side and let Destroy() close async_
9086
uv_close(reinterpret_cast<uv_handle_t*>(&wd->timer_), NULL);
91-
92-
// UV_RUN_DEFAULT so that libuv has a chance to clean up.
93-
uv_run(wd->loop_, UV_RUN_DEFAULT);
9487
}
9588

9689

src/node_watchdog.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ class Watchdog {
4545
uv_loop_t* loop_;
4646
uv_async_t async_;
4747
uv_timer_t timer_;
48-
bool thread_created_;
4948
bool destroyed_;
5049
};
5150

0 commit comments

Comments
 (0)