11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci#ifndef SRC_SPAWN_SYNC_H_
231cb0ef41Sopenharmony_ci#define SRC_SPAWN_SYNC_H_
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#include "node_buffer.h"
281cb0ef41Sopenharmony_ci#include "uv.h"
291cb0ef41Sopenharmony_ci#include "v8.h"
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_cinamespace node {
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ciclass SyncProcessOutputBuffer;
361cb0ef41Sopenharmony_ciclass SyncProcessStdioPipe;
371cb0ef41Sopenharmony_ciclass SyncProcessRunner;
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ciclass SyncProcessOutputBuffer {
411cb0ef41Sopenharmony_ci  static const unsigned int kBufferSize = 65536;
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci public:
441cb0ef41Sopenharmony_ci  inline SyncProcessOutputBuffer() = default;
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ci  inline void OnAlloc(size_t suggested_size, uv_buf_t* buf) const;
471cb0ef41Sopenharmony_ci  inline void OnRead(const uv_buf_t* buf, size_t nread);
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  inline size_t Copy(char* dest) const;
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  inline unsigned int available() const;
521cb0ef41Sopenharmony_ci  inline unsigned int used() const;
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci  inline SyncProcessOutputBuffer* next() const;
551cb0ef41Sopenharmony_ci  inline void set_next(SyncProcessOutputBuffer* next);
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci private:
581cb0ef41Sopenharmony_ci  // Use unsigned int because that's what `uv_buf_init` takes.
591cb0ef41Sopenharmony_ci  mutable char data_[kBufferSize];
601cb0ef41Sopenharmony_ci  unsigned int used_ = 0;
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci  SyncProcessOutputBuffer* next_ = nullptr;
631cb0ef41Sopenharmony_ci};
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ciclass SyncProcessStdioPipe {
671cb0ef41Sopenharmony_ci  enum Lifecycle {
681cb0ef41Sopenharmony_ci    kUninitialized = 0,
691cb0ef41Sopenharmony_ci    kInitialized,
701cb0ef41Sopenharmony_ci    kStarted,
711cb0ef41Sopenharmony_ci    kClosing,
721cb0ef41Sopenharmony_ci    kClosed
731cb0ef41Sopenharmony_ci  };
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci public:
761cb0ef41Sopenharmony_ci  SyncProcessStdioPipe(SyncProcessRunner* process_handler,
771cb0ef41Sopenharmony_ci                       bool readable,
781cb0ef41Sopenharmony_ci                       bool writable,
791cb0ef41Sopenharmony_ci                       uv_buf_t input_buffer);
801cb0ef41Sopenharmony_ci  ~SyncProcessStdioPipe();
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  int Initialize(uv_loop_t* loop);
831cb0ef41Sopenharmony_ci  int Start();
841cb0ef41Sopenharmony_ci  void Close();
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci  v8::Local<v8::Object> GetOutputAsBuffer(Environment* env) const;
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  inline bool readable() const;
891cb0ef41Sopenharmony_ci  inline bool writable() const;
901cb0ef41Sopenharmony_ci  inline uv_stdio_flags uv_flags() const;
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci  inline uv_pipe_t* uv_pipe() const;
931cb0ef41Sopenharmony_ci  inline uv_stream_t* uv_stream() const;
941cb0ef41Sopenharmony_ci  inline uv_handle_t* uv_handle() const;
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci private:
971cb0ef41Sopenharmony_ci  inline size_t OutputLength() const;
981cb0ef41Sopenharmony_ci  inline void CopyOutput(char* dest) const;
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  inline void OnAlloc(size_t suggested_size, uv_buf_t* buf);
1011cb0ef41Sopenharmony_ci  inline void OnRead(const uv_buf_t* buf, ssize_t nread);
1021cb0ef41Sopenharmony_ci  inline void OnWriteDone(int result);
1031cb0ef41Sopenharmony_ci  inline void OnShutdownDone(int result);
1041cb0ef41Sopenharmony_ci  inline void OnClose();
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  inline void SetError(int error);
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_ci  static void AllocCallback(uv_handle_t* handle,
1091cb0ef41Sopenharmony_ci                            size_t suggested_size,
1101cb0ef41Sopenharmony_ci                            uv_buf_t* buf);
1111cb0ef41Sopenharmony_ci  static void ReadCallback(uv_stream_t* stream,
1121cb0ef41Sopenharmony_ci                           ssize_t nread,
1131cb0ef41Sopenharmony_ci                           const uv_buf_t* buf);
1141cb0ef41Sopenharmony_ci  static void WriteCallback(uv_write_t* req, int result);
1151cb0ef41Sopenharmony_ci  static void ShutdownCallback(uv_shutdown_t* req, int result);
1161cb0ef41Sopenharmony_ci  static void CloseCallback(uv_handle_t* handle);
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  SyncProcessRunner* process_handler_;
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  bool readable_;
1211cb0ef41Sopenharmony_ci  bool writable_;
1221cb0ef41Sopenharmony_ci  uv_buf_t input_buffer_;
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  SyncProcessOutputBuffer* first_output_buffer_;
1251cb0ef41Sopenharmony_ci  SyncProcessOutputBuffer* last_output_buffer_;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  mutable uv_pipe_t uv_pipe_;
1281cb0ef41Sopenharmony_ci  uv_write_t write_req_;
1291cb0ef41Sopenharmony_ci  uv_shutdown_t shutdown_req_;
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  Lifecycle lifecycle_;
1321cb0ef41Sopenharmony_ci};
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ciclass SyncProcessRunner {
1361cb0ef41Sopenharmony_ci  enum Lifecycle {
1371cb0ef41Sopenharmony_ci    kUninitialized = 0,
1381cb0ef41Sopenharmony_ci    kInitialized,
1391cb0ef41Sopenharmony_ci    kHandlesClosed
1401cb0ef41Sopenharmony_ci  };
1411cb0ef41Sopenharmony_ci
1421cb0ef41Sopenharmony_ci public:
1431cb0ef41Sopenharmony_ci  static void Initialize(v8::Local<v8::Object> target,
1441cb0ef41Sopenharmony_ci                         v8::Local<v8::Value> unused,
1451cb0ef41Sopenharmony_ci                         v8::Local<v8::Context> context,
1461cb0ef41Sopenharmony_ci                         void* priv);
1471cb0ef41Sopenharmony_ci  static void Spawn(const v8::FunctionCallbackInfo<v8::Value>& args);
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci private:
1501cb0ef41Sopenharmony_ci  friend class SyncProcessStdioPipe;
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  explicit SyncProcessRunner(Environment* env_);
1531cb0ef41Sopenharmony_ci  ~SyncProcessRunner();
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  inline Environment* env() const;
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  v8::MaybeLocal<v8::Object> Run(v8::Local<v8::Value> options);
1581cb0ef41Sopenharmony_ci  v8::Maybe<bool> TryInitializeAndRunLoop(v8::Local<v8::Value> options);
1591cb0ef41Sopenharmony_ci  void CloseHandlesAndDeleteLoop();
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci  void CloseStdioPipes();
1621cb0ef41Sopenharmony_ci  void CloseKillTimer();
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  void Kill();
1651cb0ef41Sopenharmony_ci  void IncrementBufferSizeAndCheckOverflow(ssize_t length);
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  void OnExit(int64_t exit_status, int term_signal);
1681cb0ef41Sopenharmony_ci  void OnKillTimerTimeout();
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  int GetError();
1711cb0ef41Sopenharmony_ci  void SetError(int error);
1721cb0ef41Sopenharmony_ci  void SetPipeError(int pipe_error);
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci  v8::Local<v8::Object> BuildResultObject();
1751cb0ef41Sopenharmony_ci  v8::Local<v8::Array> BuildOutputArray();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  v8::Maybe<int> ParseOptions(v8::Local<v8::Value> js_value);
1781cb0ef41Sopenharmony_ci  int ParseStdioOptions(v8::Local<v8::Value> js_value);
1791cb0ef41Sopenharmony_ci  int ParseStdioOption(int child_fd, v8::Local<v8::Object> js_stdio_option);
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  inline int AddStdioIgnore(uint32_t child_fd);
1821cb0ef41Sopenharmony_ci  inline int AddStdioPipe(uint32_t child_fd,
1831cb0ef41Sopenharmony_ci                          bool readable,
1841cb0ef41Sopenharmony_ci                          bool writable,
1851cb0ef41Sopenharmony_ci                          uv_buf_t input_buffer);
1861cb0ef41Sopenharmony_ci  inline int AddStdioInheritFD(uint32_t child_fd, int inherit_fd);
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  static bool IsSet(v8::Local<v8::Value> value);
1891cb0ef41Sopenharmony_ci  v8::Maybe<int> CopyJsString(v8::Local<v8::Value> js_value,
1901cb0ef41Sopenharmony_ci                              const char** target);
1911cb0ef41Sopenharmony_ci  v8::Maybe<int> CopyJsStringArray(v8::Local<v8::Value> js_value,
1921cb0ef41Sopenharmony_ci                                   char** target);
1931cb0ef41Sopenharmony_ci
1941cb0ef41Sopenharmony_ci  static void ExitCallback(uv_process_t* handle,
1951cb0ef41Sopenharmony_ci                           int64_t exit_status,
1961cb0ef41Sopenharmony_ci                           int term_signal);
1971cb0ef41Sopenharmony_ci  static void KillTimerCallback(uv_timer_t* handle);
1981cb0ef41Sopenharmony_ci  static void KillTimerCloseCallback(uv_handle_t* handle);
1991cb0ef41Sopenharmony_ci
2001cb0ef41Sopenharmony_ci  double max_buffer_;
2011cb0ef41Sopenharmony_ci  uint64_t timeout_;
2021cb0ef41Sopenharmony_ci  int kill_signal_;
2031cb0ef41Sopenharmony_ci
2041cb0ef41Sopenharmony_ci  uv_loop_t* uv_loop_;
2051cb0ef41Sopenharmony_ci
2061cb0ef41Sopenharmony_ci  uint32_t stdio_count_;
2071cb0ef41Sopenharmony_ci  uv_stdio_container_t* uv_stdio_containers_;
2081cb0ef41Sopenharmony_ci  std::vector<std::unique_ptr<SyncProcessStdioPipe>> stdio_pipes_;
2091cb0ef41Sopenharmony_ci  bool stdio_pipes_initialized_;
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  uv_process_options_t uv_process_options_;
2121cb0ef41Sopenharmony_ci  const char* file_buffer_;
2131cb0ef41Sopenharmony_ci  char* args_buffer_;
2141cb0ef41Sopenharmony_ci  char* env_buffer_;
2151cb0ef41Sopenharmony_ci  const char* cwd_buffer_;
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci  uv_process_t uv_process_;
2181cb0ef41Sopenharmony_ci  bool killed_;
2191cb0ef41Sopenharmony_ci
2201cb0ef41Sopenharmony_ci  size_t buffered_output_size_;
2211cb0ef41Sopenharmony_ci  int64_t exit_status_;
2221cb0ef41Sopenharmony_ci  int term_signal_;
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  uv_timer_t uv_timer_;
2251cb0ef41Sopenharmony_ci  bool kill_timer_initialized_;
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  // Errors that happen in one of the pipe handlers are stored in the
2281cb0ef41Sopenharmony_ci  // `pipe_error` field. They are treated as "low-priority", only to be
2291cb0ef41Sopenharmony_ci  // reported if no more serious errors happened.
2301cb0ef41Sopenharmony_ci  int error_;
2311cb0ef41Sopenharmony_ci  int pipe_error_;
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci  Lifecycle lifecycle_;
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ci  Environment* env_;
2361cb0ef41Sopenharmony_ci};
2371cb0ef41Sopenharmony_ci
2381cb0ef41Sopenharmony_ci}  // namespace node
2391cb0ef41Sopenharmony_ci
2401cb0ef41Sopenharmony_ci#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ci#endif  // SRC_SPAWN_SYNC_H_
243