Skip to content

Commit e87dfa4

Browse files
authored
Fix segfaults (#1368)
* Ensure JavaScript exceptions bubble up * Fix segfault * Fix mutex segfault * Fix segfault caused by memory leak If the database was being closed, and non-exclusive work was scheduled, it overrode the lock flag such that the state became open=false locked=false instead of open=false locked=true. This caused queued work to not be processed, leaking memory, which causes a segfault during napi cleanup. Make the same changes to other methods for safe measure.
1 parent c9caae4 commit e87dfa4

File tree

7 files changed

+109
-114
lines changed

7 files changed

+109
-114
lines changed

src/backup.cc

+13-16
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ void Backup::Process() {
3131
}
3232

3333
while (inited && !locked && !queue.empty()) {
34-
Call* call = queue.front();
34+
std::unique_ptr<Call> call(queue.front());
3535
queue.pop();
3636

3737
call->callback(call->baton);
38-
delete call;
3938
}
4039
}
4140

@@ -86,21 +85,17 @@ void Backup::CleanQueue() {
8685

8786
// Clear out the queue so that this object can get GC'ed.
8887
while (!queue.empty()) {
89-
Call* call = queue.front();
88+
std::unique_ptr<Call> call(queue.front());
9089
queue.pop();
9190

92-
Napi::Function cb = call->baton->callback.Value();
91+
std::unique_ptr<Baton> baton(call->baton);
92+
Napi::Function cb = baton->callback.Value();
9393

9494
if (inited && !cb.IsEmpty() &&
9595
cb.IsFunction()) {
9696
TRY_CATCH_CALL(Value(), cb, 1, argv);
9797
called = true;
9898
}
99-
100-
// We don't call the actual callback, so we have to make sure that
101-
// the baton gets destroyed.
102-
delete call->baton;
103-
delete call;
10499
}
105100

106101
// When we couldn't call a callback function, emit an error on the
@@ -113,13 +108,12 @@ void Backup::CleanQueue() {
113108
else while (!queue.empty()) {
114109
// Just delete all items in the queue; we already fired an event when
115110
// initializing the backup failed.
116-
Call* call = queue.front();
111+
std::unique_ptr<Call> call(queue.front());
117112
queue.pop();
118113

119114
// We don't call the actual callback, so we have to make sure that
120115
// the baton gets destroyed.
121116
delete call->baton;
122-
delete call;
123117
}
124118
}
125119

@@ -220,13 +214,14 @@ void Backup::Work_Initialize(napi_env e, void* data) {
220214
}
221215

222216
void Backup::Work_AfterInitialize(napi_env e, napi_status status, void* data) {
223-
BACKUP_INIT(InitializeBaton);
217+
std::unique_ptr<InitializeBaton> baton(static_cast<InitializeBaton*>(data));
218+
Backup* backup = baton->backup;
224219

225220
Napi::Env env = backup->Env();
226221
Napi::HandleScope scope(env);
227222

228223
if (backup->status != SQLITE_OK) {
229-
Error(baton);
224+
Error(baton.get());
230225
backup->FinishAll();
231226
}
232227
else {
@@ -282,7 +277,8 @@ void Backup::Work_Step(napi_env e, void* data) {
282277
}
283278

284279
void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) {
285-
BACKUP_INIT(StepBaton);
280+
std::unique_ptr<StepBaton> baton(static_cast<StepBaton*>(data));
281+
Backup* backup = baton->backup;
286282

287283
Napi::Env env = backup->Env();
288284
Napi::HandleScope scope(env);
@@ -294,7 +290,7 @@ void Backup::Work_AfterStep(napi_env e, napi_status status, void* data) {
294290
}
295291

296292
if (backup->status != SQLITE_OK && backup->status != SQLITE_DONE) {
297-
Error(baton);
293+
Error(baton.get());
298294
}
299295
else {
300296
// Fire callbacks.
@@ -329,7 +325,8 @@ void Backup::Work_Finish(napi_env e, void* data) {
329325
}
330326

331327
void Backup::Work_AfterFinish(napi_env e, napi_status status, void* data) {
332-
BACKUP_INIT(Baton);
328+
std::unique_ptr<Baton> baton(static_cast<Baton*>(data));
329+
Backup* backup = baton->backup;
333330

334331
Napi::Env env = backup->Env();
335332
Napi::HandleScope scope(env);

src/backup.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ class Backup : public Napi::ObjectWrap<Backup> {
9696
static Napi::Object Init(Napi::Env env, Napi::Object exports);
9797

9898
struct Baton {
99-
napi_async_work request;
99+
napi_async_work request = NULL;
100100
Backup* backup;
101101
Napi::FunctionReference callback;
102102

@@ -105,6 +105,7 @@ class Backup : public Napi::ObjectWrap<Backup> {
105105
callback.Reset(cb_, 1);
106106
}
107107
virtual ~Baton() {
108+
if (request) napi_delete_async_work(backup->Env(), request);
108109
backup->Unref();
109110
callback.Reset();
110111
}

0 commit comments

Comments
 (0)