refactor: add a wrapper for wrangling uv handles. (#25332)
* refactor: add a wrapper for wrangling uv handles. Part 1 of a fix for #25248, #22069. Place the uv_asyncs owned by NodeBindings, ElectronBindings inside a new UvHandle wrapper class which manages uv_handles' need for their closed() callback to be invoked before the handles' memory can be freed. * chore: make lint happy * refactor: use DCHECK_EQ() instead of DCHECK() * refactor: fix oops
This commit is contained in:
parent
a3389d017f
commit
70e3aa0182
4 changed files with 78 additions and 28 deletions
|
@ -5,6 +5,8 @@
|
|||
#ifndef SHELL_COMMON_NODE_BINDINGS_H_
|
||||
#define SHELL_COMMON_NODE_BINDINGS_H_
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
|
@ -24,6 +26,54 @@ class IsolateData;
|
|||
|
||||
namespace electron {
|
||||
|
||||
// A helper class to manage uv_handle_t types, e.g. uv_async_t.
|
||||
//
|
||||
// As per the uv docs: "uv_close() MUST be called on each handle before
|
||||
// memory is released. Moreover, the memory can only be released in
|
||||
// close_cb or after it has returned." This class encapsulates the work
|
||||
// needed to follow those requirements.
|
||||
template <typename T,
|
||||
typename std::enable_if<
|
||||
// these are the C-style 'subclasses' of uv_handle_t
|
||||
std::is_same<T, uv_async_t>::value ||
|
||||
std::is_same<T, uv_check_t>::value ||
|
||||
std::is_same<T, uv_fs_event_t>::value ||
|
||||
std::is_same<T, uv_fs_poll_t>::value ||
|
||||
std::is_same<T, uv_idle_t>::value ||
|
||||
std::is_same<T, uv_pipe_t>::value ||
|
||||
std::is_same<T, uv_poll_t>::value ||
|
||||
std::is_same<T, uv_prepare_t>::value ||
|
||||
std::is_same<T, uv_process_t>::value ||
|
||||
std::is_same<T, uv_signal_t>::value ||
|
||||
std::is_same<T, uv_stream_t>::value ||
|
||||
std::is_same<T, uv_tcp_t>::value ||
|
||||
std::is_same<T, uv_timer_t>::value ||
|
||||
std::is_same<T, uv_tty_t>::value ||
|
||||
std::is_same<T, uv_udp_t>::value>::type* = nullptr>
|
||||
class UvHandle {
|
||||
public:
|
||||
UvHandle() : t_(new T) {}
|
||||
~UvHandle() { reset(); }
|
||||
T* get() { return t_; }
|
||||
uv_handle_t* handle() { return reinterpret_cast<uv_handle_t*>(t_); }
|
||||
|
||||
void reset() {
|
||||
auto* h = handle();
|
||||
if (h != nullptr) {
|
||||
DCHECK_EQ(0, uv_is_closing(h));
|
||||
uv_close(h, OnClosed);
|
||||
t_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void OnClosed(uv_handle_t* handle) {
|
||||
delete reinterpret_cast<T*>(handle);
|
||||
}
|
||||
|
||||
T* t_ = {};
|
||||
};
|
||||
|
||||
class NodeBindings {
|
||||
public:
|
||||
enum class BrowserEnvironment { BROWSER, RENDERER, WORKER };
|
||||
|
@ -95,7 +145,7 @@ class NodeBindings {
|
|||
uv_loop_t worker_loop_;
|
||||
|
||||
// Dummy handle to make uv's loop not quit.
|
||||
uv_async_t dummy_uv_handle_;
|
||||
UvHandle<uv_async_t> dummy_uv_handle_;
|
||||
|
||||
// Thread for polling events.
|
||||
uv_thread_t embed_thread_;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue