Skip to content

Commit 558427a

Browse files
committed
Make event queue shared between nsfw and native implementation
Don't create an EventBaton which can be leaked according to the documentation in uv_async_send.
1 parent f50e945 commit 558427a

File tree

4 files changed

+31
-59
lines changed

4 files changed

+31
-59
lines changed

includes/NSFW.h

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#ifndef NSFW_H
22
#define NSFW_H
33

4+
#include "Queue.h"
45
#include "NativeInterface.h"
56
#include <nan.h>
67
#include <uv.h>
@@ -13,12 +14,15 @@ class NSFW : public ObjectWrap {
1314
public:
1415
static NAN_MODULE_INIT(Init);
1516

16-
static void cleanupEventCallback(void *arg);
1717
static void fireErrorCallback(uv_async_t *handle);
1818
static void fireEventCallback(uv_async_t *handle);
1919
static void pollForEvents(void *arg);
2020

2121
Persistent<v8::Object> mPersistentHandle;
22+
private:
23+
NSFW(uint32_t debounceMS, std::string path, Callback *eventCallback, Callback *errorCallback);
24+
~NSFW();
25+
2226
uint32_t mDebounceMS;
2327
uv_async_t mErrorCallbackAsync;
2428
uv_async_t mEventCallbackAsync;
@@ -30,20 +34,13 @@ class NSFW : public ObjectWrap {
3034
std::string mPath;
3135
uv_thread_t mPollThread;
3236
std::atomic<bool> mRunning;
33-
private:
34-
NSFW(uint32_t debounceMS, std::string path, Callback *eventCallback, Callback *errorCallback);
35-
~NSFW();
37+
std::shared_ptr<EventQueue> mQueue;
3638

3739
struct ErrorBaton {
3840
NSFW *nsfw;
3941
std::string error;
4042
};
4143

42-
struct EventBaton {
43-
NSFW *nsfw;
44-
std::unique_ptr<std::vector<std::unique_ptr<Event>>> events;
45-
};
46-
4744
static NAN_METHOD(JSNew);
4845

4946
static NAN_METHOD(Start);

includes/NativeInterface.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ using NativeImplementation = InotifyService;
1717

1818
class NativeInterface {
1919
public:
20-
NativeInterface(const std::string &path);
20+
NativeInterface(const std::string &path, std::shared_ptr<EventQueue> queue);
2121
~NativeInterface();
2222

2323
std::string getError();
24-
std::unique_ptr<std::vector<std::unique_ptr<Event>>> getEvents();
2524
bool hasErrored();
2625
bool isWatching();
2726

2827
private:
29-
std::shared_ptr<EventQueue> mQueue;
3028
std::unique_ptr<NativeImplementation> mNativeInterface;
3129
};
3230

src/NSFW.cpp

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ NSFW::NSFW(uint32_t debounceMS, std::string path, Callback *eventCallback, Callb
1818
mInterface(NULL),
1919
mInterfaceLockValid(false),
2020
mPath(path),
21-
mRunning(false) {
21+
mRunning(false),
22+
mQueue(std::make_shared<EventQueue>())
23+
{
2224
HandleScope scope;
2325
v8::Local<v8::Object> obj = New<v8::Object>();
2426
mPersistentHandle.Reset(obj);
@@ -37,11 +39,6 @@ NSFW::~NSFW() {
3739
}
3840
}
3941

40-
void NSFW::cleanupEventCallback(void *arg) {
41-
EventBaton *baton = (EventBaton *)arg;
42-
delete baton;
43-
}
44-
4542
void NSFW::fireErrorCallback(uv_async_t *handle) {
4643
Nan::HandleScope scope;
4744
ErrorBaton *baton = (ErrorBaton *)handle->data;
@@ -54,33 +51,27 @@ void NSFW::fireErrorCallback(uv_async_t *handle) {
5451

5552
void NSFW::fireEventCallback(uv_async_t *handle) {
5653
Nan::HandleScope scope;
57-
EventBaton *baton = (EventBaton *)handle->data;
58-
if (baton->events->empty()) {
59-
uv_thread_t cleanup;
60-
uv_thread_create(&cleanup, NSFW::cleanupEventCallback, baton);
61-
62-
#if defined(__APPLE_CC__) || defined(__linux__) || defined(__FreeBSD__)
63-
pthread_detach(cleanup);
64-
#endif
65-
54+
NSFW *nsfw = (NSFW *)handle->data;
55+
auto events = nsfw->mQueue->dequeueAll();
56+
if (events == nullptr) {
6657
return;
6758
}
6859

69-
v8::Local<v8::Array> eventArray = New<v8::Array>((int)baton->events->size());
60+
v8::Local<v8::Array> eventArray = New<v8::Array>((int)events->size());
7061

71-
for (unsigned int i = 0; i < baton->events->size(); ++i) {
62+
for (unsigned int i = 0; i < events->size(); ++i) {
7263
v8::Local<v8::Object> jsEvent = New<v8::Object>();
7364

7465

75-
jsEvent->Set(New<v8::String>("action").ToLocalChecked(), New<v8::Number>((*baton->events)[i]->type));
76-
jsEvent->Set(New<v8::String>("directory").ToLocalChecked(), New<v8::String>((*baton->events)[i]->fromDirectory).ToLocalChecked());
66+
jsEvent->Set(New<v8::String>("action").ToLocalChecked(), New<v8::Number>((*events)[i]->type));
67+
jsEvent->Set(New<v8::String>("directory").ToLocalChecked(), New<v8::String>((*events)[i]->fromDirectory).ToLocalChecked());
7768

78-
if ((*baton->events)[i]->type == RENAMED) {
79-
jsEvent->Set(New<v8::String>("oldFile").ToLocalChecked(), New<v8::String>((*baton->events)[i]->fromFile).ToLocalChecked());
80-
jsEvent->Set(New<v8::String>("newDirectory").ToLocalChecked(), New<v8::String>((*baton->events)[i]->toDirectory).ToLocalChecked());
81-
jsEvent->Set(New<v8::String>("newFile").ToLocalChecked(), New<v8::String>((*baton->events)[i]->toFile).ToLocalChecked());
69+
if ((*events)[i]->type == RENAMED) {
70+
jsEvent->Set(New<v8::String>("oldFile").ToLocalChecked(), New<v8::String>((*events)[i]->fromFile).ToLocalChecked());
71+
jsEvent->Set(New<v8::String>("newDirectory").ToLocalChecked(), New<v8::String>((*events)[i]->toDirectory).ToLocalChecked());
72+
jsEvent->Set(New<v8::String>("newFile").ToLocalChecked(), New<v8::String>((*events)[i]->toFile).ToLocalChecked());
8273
} else {
83-
jsEvent->Set(New<v8::String>("file").ToLocalChecked(), New<v8::String>((*baton->events)[i]->fromFile).ToLocalChecked());
74+
jsEvent->Set(New<v8::String>("file").ToLocalChecked(), New<v8::String>((*events)[i]->fromFile).ToLocalChecked());
8475
}
8576

8677
eventArray->Set(i, jsEvent);
@@ -90,14 +81,7 @@ void NSFW::fireEventCallback(uv_async_t *handle) {
9081
eventArray
9182
};
9283

93-
baton->nsfw->mEventCallback->Call(1, argv);
94-
95-
uv_thread_t cleanup;
96-
uv_thread_create(&cleanup, NSFW::cleanupEventCallback, baton);
97-
98-
#if defined(__APPLE_CC__) || defined(__linux__) || defined(__FreeBSD__)
99-
pthread_detach(cleanup);
100-
#endif
84+
nsfw->mEventCallback->Call(1, argv);
10185
}
10286

10387
void NSFW::pollForEvents(void *arg) {
@@ -116,18 +100,14 @@ void NSFW::pollForEvents(void *arg) {
116100
uv_mutex_unlock(&nsfw->mInterfaceLock);
117101
break;
118102
}
119-
auto events = nsfw->mInterface->getEvents();
120-
if (events == NULL) {
103+
104+
if (nsfw->mQueue->count() == 0) {
121105
uv_mutex_unlock(&nsfw->mInterfaceLock);
122106
sleep_for_ms(50);
123107
continue;
124108
}
125109

126-
EventBaton *baton = new EventBaton;
127-
baton->nsfw = nsfw;
128-
baton->events = std::move(events);
129-
130-
nsfw->mEventCallbackAsync.data = (void *)baton;
110+
nsfw->mEventCallbackAsync.data = (void *)nsfw;
131111
uv_async_send(&nsfw->mEventCallbackAsync);
132112

133113
uv_mutex_unlock(&nsfw->mInterfaceLock);
@@ -230,7 +210,8 @@ void NSFW::StartWorker::Execute() {
230210
return;
231211
}
232212

233-
mNSFW->mInterface = new NativeInterface(mNSFW->mPath);
213+
mNSFW->mQueue->clear();
214+
mNSFW->mInterface = new NativeInterface(mNSFW->mPath, mNSFW->mQueue);
234215
if (mNSFW->mInterface->isWatching()) {
235216
mNSFW->mRunning = true;
236217
uv_thread_create(&mNSFW->mPollThread, NSFW::pollForEvents, mNSFW);
@@ -306,6 +287,7 @@ void NSFW::StopWorker::Execute() {
306287
uv_mutex_lock(&mNSFW->mInterfaceLock);
307288
delete mNSFW->mInterface;
308289
mNSFW->mInterface = NULL;
290+
mNSFW->mQueue->clear();
309291

310292
uv_mutex_unlock(&mNSFW->mInterfaceLock);
311293
}

src/NativeInterface.cpp

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#include "../includes/NativeInterface.h"
22

3-
NativeInterface::NativeInterface(const std::string &path) {
4-
mQueue = std::make_shared<EventQueue>();
5-
mNativeInterface.reset(new NativeImplementation(mQueue, path));
3+
NativeInterface::NativeInterface(const std::string &path, std::shared_ptr<EventQueue> queue) {
4+
mNativeInterface.reset(new NativeImplementation(queue, path));
65
}
76

87
NativeInterface::~NativeInterface() {
@@ -13,10 +12,6 @@ std::string NativeInterface::getError() {
1312
return mNativeInterface->getError();
1413
}
1514

16-
std::unique_ptr<std::vector<std::unique_ptr<Event>>> NativeInterface::getEvents() {
17-
return mQueue->dequeueAll();
18-
}
19-
2015
bool NativeInterface::hasErrored() {
2116
return mNativeInterface->hasErrored();
2217
}

0 commit comments

Comments
 (0)