summaryrefslogtreecommitdiff
path: root/src/node_worker.h
blob: 7b1311734a2a4a26e4b5ea8a3fc2a07d24f0943c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef SRC_NODE_WORKER_H_
#define SRC_NODE_WORKER_H_

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include <unordered_map>
#include "node_messaging.h"
#include "uv.h"

namespace node {
namespace worker {

class WorkerThreadData;

enum ResourceLimits {
  kMaxYoungGenerationSizeMb,
  kMaxOldGenerationSizeMb,
  kCodeRangeSizeMb,
  kTotalResourceLimitCount
};

// A worker thread, as represented in its parent thread.
class Worker : public AsyncWrap {
 public:
  Worker(Environment* env,
         v8::Local<v8::Object> wrap,
         const std::string& url,
         std::shared_ptr<PerIsolateOptions> per_isolate_opts,
         std::vector<std::string>&& exec_argv);
  ~Worker() override;

  // Run the worker. This is only called from the worker thread.
  void Run();

  // Forcibly exit the thread with a specified exit code. This may be called
  // from any thread.
  void Exit(int code);

  // Wait for the worker thread to stop (in a blocking manner).
  void JoinThread();

  void MemoryInfo(MemoryTracker* tracker) const override {
    tracker->TrackField("parent_port", parent_port_);
    tracker->TrackInlineField(&on_thread_finished_, "on_thread_finished_");
  }

  SET_MEMORY_INFO_NAME(Worker)
  SET_SELF_SIZE(Worker)

  bool is_stopped() const;

  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void CloneParentEnvVars(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  static void SetEnvVars(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void StartThread(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void StopThread(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Ref(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void Unref(const v8::FunctionCallbackInfo<v8::Value>& args);
  static void GetResourceLimits(
      const v8::FunctionCallbackInfo<v8::Value>& args);
  v8::Local<v8::Float64Array> GetResourceLimits(v8::Isolate* isolate) const;

 private:
  void CreateEnvMessagePort(Environment* env);
  static size_t NearHeapLimit(void* data, size_t current_heap_limit,
                              size_t initial_heap_limit);

  std::shared_ptr<PerIsolateOptions> per_isolate_opts_;
  std::vector<std::string> exec_argv_;
  std::vector<std::string> argv_;

  MultiIsolatePlatform* platform_;
  v8::Isolate* isolate_ = nullptr;
  bool start_profiler_idle_notifier_;
  uv_thread_t tid_;

#if HAVE_INSPECTOR
  std::unique_ptr<inspector::ParentInspectorHandle> inspector_parent_handle_;
#endif

  // This mutex protects access to all variables listed below it.
  mutable Mutex mutex_;

  bool thread_joined_ = true;
  const char* custom_error_ = nullptr;
  int exit_code_ = 0;
  uint64_t thread_id_ = -1;
  uintptr_t stack_base_ = 0;

  // Custom resource constraints:
  double resource_limits_[kTotalResourceLimitCount];
  void UpdateResourceConstraints(v8::ResourceConstraints* constraints);

  // Full size of the thread's stack.
  static constexpr size_t kStackSize = 4 * 1024 * 1024;
  // Stack buffer size that is not available to the JS engine.
  static constexpr size_t kStackBufferSize = 192 * 1024;

  std::unique_ptr<MessagePortData> child_port_data_;
  std::shared_ptr<KVStore> env_vars_;

  // The child port is kept alive by the child Environment's persistent
  // handle to it, as long as that child Environment exists.
  MessagePort* child_port_ = nullptr;
  // This is always kept alive because the JS object associated with the Worker
  // instance refers to it via its [kPort] property.
  MessagePort* parent_port_ = nullptr;

  AsyncRequest on_thread_finished_;

  // A raw flag that is used by creator and worker threads to
  // sync up on pre-mature termination of worker  - while in the
  // warmup phase.  Once the worker is fully warmed up, use the
  // async handle of the worker's Environment for the same purpose.
  bool stopped_ = true;

  // The real Environment of the worker object. It has a lesser
  // lifespan than the worker object itself - comes to life
  // when the worker thread creates a new Environment, and gets
  // destroyed alongwith the worker thread.
  Environment* env_ = nullptr;

  friend class WorkerThreadData;
};

}  // namespace worker
}  // namespace node

#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS


#endif  // SRC_NODE_WORKER_H_