Clean exit, remove forcefully_free
This commit is contained in:
parent
319eea90bd
commit
a43675c197
@ -37,9 +37,3 @@ const app = uWS./*SSL*/App({
|
|||||||
console.log('Failed to listen to port ' + port);
|
console.log('Failed to listen to port ' + port);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* This is questionable */
|
|
||||||
process.on('beforeExit', () => {
|
|
||||||
console.log('Forcefully freeing app now');
|
|
||||||
app.forcefully_free();
|
|
||||||
});
|
|
||||||
|
@ -206,14 +206,6 @@ void uWS_App_listen(const FunctionCallbackInfo<Value> &args) {
|
|||||||
args.GetReturnValue().Set(args.Holder());
|
args.GetReturnValue().Set(args.Holder());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mostly indended for debugging memory leaks */
|
|
||||||
template <typename APP>
|
|
||||||
void uWS_App_forcefully_free(const FunctionCallbackInfo<Value> &args) {
|
|
||||||
APP *app = (APP *) args.Holder()->GetAlignedPointerFromInternalField(0);
|
|
||||||
|
|
||||||
delete app;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename APP>
|
template <typename APP>
|
||||||
void uWS_App(const FunctionCallbackInfo<Value> &args) {
|
void uWS_App(const FunctionCallbackInfo<Value> &args) {
|
||||||
Local<FunctionTemplate> appTemplate = FunctionTemplate::New(isolate);
|
Local<FunctionTemplate> appTemplate = FunctionTemplate::New(isolate);
|
||||||
@ -336,11 +328,15 @@ void uWS_App(const FunctionCallbackInfo<Value> &args) {
|
|||||||
appTemplate->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "ws"), FunctionTemplate::New(isolate, uWS_App_ws<APP>));
|
appTemplate->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "ws"), FunctionTemplate::New(isolate, uWS_App_ws<APP>));
|
||||||
appTemplate->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "listen"), FunctionTemplate::New(isolate, uWS_App_listen<APP>));
|
appTemplate->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "listen"), FunctionTemplate::New(isolate, uWS_App_listen<APP>));
|
||||||
|
|
||||||
/* forcefully_free is unsafe for end-users to use, but nice to track memory leaks with ASAN */
|
|
||||||
appTemplate->PrototypeTemplate()->Set(String::NewFromUtf8(isolate, "forcefully_free"), FunctionTemplate::New(isolate, uWS_App_forcefully_free<APP>));
|
|
||||||
|
|
||||||
Local<Object> localApp = appTemplate->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
Local<Object> localApp = appTemplate->GetFunction()->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
||||||
localApp->SetAlignedPointerInInternalField(0, app);
|
localApp->SetAlignedPointerInInternalField(0, app);
|
||||||
|
|
||||||
|
/* Add this to our delete list */
|
||||||
|
if constexpr (std::is_same<APP, uWS::SSLApp>::value) {
|
||||||
|
sslApps.emplace_back(app);
|
||||||
|
} else {
|
||||||
|
apps.emplace_back(app);
|
||||||
|
}
|
||||||
|
|
||||||
args.GetReturnValue().Set(localApp);
|
args.GetReturnValue().Set(localApp);
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ using namespace v8;
|
|||||||
|
|
||||||
/* These two are definitely static */
|
/* These two are definitely static */
|
||||||
Isolate *isolate;
|
Isolate *isolate;
|
||||||
|
bool valid = true;
|
||||||
|
|
||||||
|
/* We hold all apps until free */
|
||||||
|
std::vector<std::unique_ptr<uWS::App>> apps;
|
||||||
|
std::vector<std::unique_ptr<uWS::SSLApp>> sslApps;
|
||||||
|
|
||||||
#include "Utilities.h"
|
#include "Utilities.h"
|
||||||
#include "WebSocketWrapper.h"
|
#include "WebSocketWrapper.h"
|
||||||
@ -32,10 +37,18 @@ Isolate *isolate;
|
|||||||
#include "HttpRequestWrapper.h"
|
#include "HttpRequestWrapper.h"
|
||||||
#include "AppWrapper.h"
|
#include "AppWrapper.h"
|
||||||
|
|
||||||
/* Used for debugging */
|
/* Todo: Apps should be freed once the GC says so BUT ALWAYS before freeing the loop */
|
||||||
void print(const FunctionCallbackInfo<Value> &args) {
|
|
||||||
NativeString nativeString(isolate, args[0]);
|
/* This has to be called in beforeExit, but exit also seems okay */
|
||||||
std::cout << nativeString.getString() << std::endl;
|
void uWS_free(const FunctionCallbackInfo<Value> &args) {
|
||||||
|
if (valid) {
|
||||||
|
/* Freeing apps here, it could be done earlier but not sooner */
|
||||||
|
apps.clear();
|
||||||
|
sslApps.clear();
|
||||||
|
/* Freeing the loop here means we give time for our timers to close, etc */
|
||||||
|
uWS::Loop::get()->free();
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* todo: Put this function and all inits of it in its own header */
|
/* todo: Put this function and all inits of it in its own header */
|
||||||
@ -50,13 +63,13 @@ void Main(Local<Object> exports) {
|
|||||||
/* We want this so that we can redefine process.nextTick to using the V8 native microtask queue */
|
/* We want this so that we can redefine process.nextTick to using the V8 native microtask queue */
|
||||||
isolate->SetMicrotasksPolicy(MicrotasksPolicy::kAuto);
|
isolate->SetMicrotasksPolicy(MicrotasksPolicy::kAuto);
|
||||||
|
|
||||||
/* Hook up our timers */
|
/* Integrate with existing libuv loop, we just pass a boolean basically */
|
||||||
us_loop_integrate((us_loop *) uWS::Loop::defaultLoop());
|
uWS::Loop::get((void *) 1);
|
||||||
|
|
||||||
/* uWS namespace */
|
/* uWS namespace */
|
||||||
exports->Set(String::NewFromUtf8(isolate, "App"), FunctionTemplate::New(isolate, uWS_App<uWS::App>)->GetFunction());
|
exports->Set(String::NewFromUtf8(isolate, "App"), FunctionTemplate::New(isolate, uWS_App<uWS::App>)->GetFunction());
|
||||||
exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App<uWS::SSLApp>)->GetFunction());
|
exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App<uWS::SSLApp>)->GetFunction());
|
||||||
exports->Set(String::NewFromUtf8(isolate, "print"), FunctionTemplate::New(isolate, print)->GetFunction());
|
exports->Set(String::NewFromUtf8(isolate, "free"), FunctionTemplate::New(isolate, uWS_free)->GetFunction());
|
||||||
|
|
||||||
/* Expose some µSockets functions directly under uWS namespace */
|
/* Expose some µSockets functions directly under uWS namespace */
|
||||||
exports->Set(String::NewFromUtf8(isolate, "us_listen_socket_close"), FunctionTemplate::New(isolate, uWS_us_listen_socket_close)->GetFunction());
|
exports->Set(String::NewFromUtf8(isolate, "us_listen_socket_close"), FunctionTemplate::New(isolate, uWS_us_listen_socket_close)->GetFunction());
|
||||||
|
@ -24,6 +24,11 @@ module.exports = (() => {
|
|||||||
f(...args);
|
f(...args);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
/* You are not allowed to use the lib past here */
|
||||||
|
process.on('exit', () => {
|
||||||
|
uWS.free();
|
||||||
|
});
|
||||||
|
|
||||||
return uWS;
|
return uWS;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('This version of µWS is not compatible with your Node.js build.\n\n' + e.toString());
|
throw new Error('This version of µWS is not compatible with your Node.js build.\n\n' + e.toString());
|
||||||
|
@ -71,10 +71,3 @@ listenWithSettings({
|
|||||||
ssl: false,
|
ssl: false,
|
||||||
compression: uWS.DEDICATED_COMPRESSOR
|
compression: uWS.DEDICATED_COMPRESSOR
|
||||||
});
|
});
|
||||||
|
|
||||||
/* This is required to check for memory leaks */
|
|
||||||
process.on('exit', () => {
|
|
||||||
apps.forEach((a) => {
|
|
||||||
a.app.forcefully_free();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
@ -201,9 +201,3 @@ const app = uWS./*SSL*/App({
|
|||||||
listenSocket = token;
|
listenSocket = token;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Yes we do this crazy thing here */
|
|
||||||
process.on('beforeExit', () => {
|
|
||||||
uWS.print('Exiting now');
|
|
||||||
app.forcefully_free();
|
|
||||||
});
|
|
@ -1 +1 @@
|
|||||||
Subproject commit 6801ab8969660a0d82b8f84f585feefabebb16fa
|
Subproject commit 35e6bad33b20c3e630e53b16c16546d2572bccfa
|
Loading…
Reference in New Issue
Block a user