615e1b9b888d6f72498d7f7fea64f5ff8eedf699
[platform/upstream/nodejs.git] / src / spawn_sync.h
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 #ifndef SRC_SPAWN_SYNC_H_
23 #define SRC_SPAWN_SYNC_H_
24
25 #include "node.h"
26 #include "node_buffer.h"
27
28 namespace node {
29
30 using v8::Array;
31 using v8::Context;
32 using v8::FunctionCallbackInfo;
33 using v8::Handle;
34 using v8::HandleScope;
35 using v8::Integer;
36 using v8::Isolate;
37 using v8::Local;
38 using v8::Null;
39 using v8::Number;
40 using v8::Object;
41 using v8::String;
42 using v8::Value;
43
44
45 class SyncProcessOutputBuffer;
46 class SyncProcessStdioPipe;
47 class SyncProcessRunner;
48
49
50 class SyncProcessOutputBuffer {
51   static const unsigned int kBufferSize = 65536;
52
53  public:
54   inline SyncProcessOutputBuffer();
55
56   inline void OnAlloc(size_t suggested_size, uv_buf_t* buf) const;
57   inline void OnRead(const uv_buf_t* buf, size_t nread);
58
59   inline size_t Copy(char* dest) const;
60
61   inline unsigned int available() const;
62   inline unsigned int used() const;
63
64   inline SyncProcessOutputBuffer* next() const;
65   inline void set_next(SyncProcessOutputBuffer* next);
66
67  private:
68   // Use unsigned int because that's what `uv_buf_init` takes.
69   mutable char data_[kBufferSize];
70   unsigned int used_;
71
72   SyncProcessOutputBuffer* next_;
73 };
74
75
76 class SyncProcessStdioPipe {
77   enum Lifecycle {
78     kUninitialized = 0,
79     kInitialized,
80     kStarted,
81     kClosing,
82     kClosed
83   };
84
85  public:
86   SyncProcessStdioPipe(SyncProcessRunner* process_handler,
87                        bool readable,
88                        bool writable,
89                        uv_buf_t input_buffer);
90   ~SyncProcessStdioPipe();
91
92   int Initialize(uv_loop_t* loop);
93   int Start();
94   void Close();
95
96   Local<Object> GetOutputAsBuffer() const;
97
98   inline bool readable() const;
99   inline bool writable() const;
100   inline uv_stdio_flags uv_flags() const;
101
102   inline uv_pipe_t* uv_pipe() const;
103   inline uv_stream_t* uv_stream() const;
104   inline uv_handle_t* uv_handle() const;
105
106  private:
107   inline size_t OutputLength() const;
108   inline void CopyOutput(char* dest) const;
109
110   inline void OnAlloc(size_t suggested_size, uv_buf_t* buf);
111   inline void OnRead(const uv_buf_t* buf, ssize_t nread);
112   inline void OnWriteDone(int result);
113   inline void OnShutdownDone(int result);
114   inline void OnClose();
115
116   inline void SetError(int error);
117
118   static void AllocCallback(uv_handle_t* handle,
119                             size_t suggested_size,
120                             uv_buf_t* buf);
121   static void ReadCallback(uv_stream_t* stream,
122                            ssize_t nread,
123                            const uv_buf_t* buf);
124   static void WriteCallback(uv_write_t* req, int result);
125   static void ShutdownCallback(uv_shutdown_t* req, int result);
126   static void CloseCallback(uv_handle_t* handle);
127
128   SyncProcessRunner* process_handler_;
129
130   bool readable_;
131   bool writable_;
132   uv_buf_t input_buffer_;
133
134   SyncProcessOutputBuffer* first_output_buffer_;
135   SyncProcessOutputBuffer* last_output_buffer_;
136
137   mutable uv_pipe_t uv_pipe_;
138   uv_write_t write_req_;
139   uv_shutdown_t shutdown_req_;
140
141   Lifecycle lifecycle_;
142 };
143
144
145 class SyncProcessRunner {
146   enum Lifecycle {
147     kUninitialized = 0,
148     kInitialized,
149     kHandlesClosed
150   };
151
152  public:
153   static void Initialize(Handle<Object> target,
154                          Handle<Value> unused,
155                          Handle<Context> context);
156   static void Spawn(const FunctionCallbackInfo<Value>& args);
157
158  private:
159   friend class SyncProcessStdioPipe;
160
161   explicit SyncProcessRunner(Environment* env_);
162   ~SyncProcessRunner();
163
164   inline Environment* env() const;
165
166   Local<Object> Run(Local<Value> options);
167   void TryInitializeAndRunLoop(Local<Value> options);
168   void CloseHandlesAndDeleteLoop();
169
170   void CloseStdioPipes();
171   void CloseKillTimer();
172
173   void Kill();
174   void IncrementBufferSizeAndCheckOverflow(ssize_t length);
175
176   void OnExit(int64_t exit_status, int term_signal);
177   void OnKillTimerTimeout();
178
179   int GetError();
180   void SetError(int error);
181   void SetPipeError(int pipe_error);
182
183   Local<Object> BuildResultObject();
184   Local<Array> BuildOutputArray();
185
186   int ParseOptions(Local<Value> js_value);
187   int ParseStdioOptions(Local<Value> js_value);
188   int ParseStdioOption(int child_fd, Local<Object> js_stdio_option);
189
190   inline int AddStdioIgnore(uint32_t child_fd);
191   inline int AddStdioPipe(uint32_t child_fd,
192                           bool readable,
193                           bool writable,
194                           uv_buf_t input_buffer);
195   inline int AddStdioInheritFD(uint32_t child_fd, int inherit_fd);
196
197   static bool IsSet(Local<Value> value);
198   template <typename t> static bool CheckRange(Local<Value> js_value);
199   int CopyJsString(Local<Value> js_value, const char** target);
200   int CopyJsStringArray(Local<Value> js_value, char** target);
201
202   static void ExitCallback(uv_process_t* handle,
203                            int64_t exit_status,
204                            int term_signal);
205   static void KillTimerCallback(uv_timer_t* handle);
206   static void KillTimerCloseCallback(uv_handle_t* handle);
207
208   size_t max_buffer_;
209   uint64_t timeout_;
210   int kill_signal_;
211
212   uv_loop_t* uv_loop_;
213
214   uint32_t stdio_count_;
215   uv_stdio_container_t* uv_stdio_containers_;
216   SyncProcessStdioPipe** stdio_pipes_;
217   bool stdio_pipes_initialized_;
218
219   uv_process_options_t uv_process_options_;
220   const char* file_buffer_;
221   char* args_buffer_;
222   char* env_buffer_;
223   const char* cwd_buffer_;
224
225   uv_process_t uv_process_;
226   bool killed_;
227
228   size_t buffered_output_size_;
229   int64_t exit_status_;
230   int term_signal_;
231
232   uv_timer_t uv_timer_;
233   bool kill_timer_initialized_;
234
235   // Errors that happen in one of the pipe handlers are stored in the
236   // `pipe_error` field. They are treated as "low-priority", only to be
237   // reported if no more serious errors happened.
238   int error_;
239   int pipe_error_;
240
241   Lifecycle lifecycle_;
242
243   Environment* env_;
244 };
245 }
246
247 #endif  // SRC_SPAWN_SYNC_H_