OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 class _ProcessStartStatus { | 5 class _ProcessStartStatus { |
6 int _errorCode; // Set to OS error code if process start failed. | 6 int _errorCode; // Set to OS error code if process start failed. |
7 String _errorMessage; // Set to OS error message if process start failed. | 7 String _errorMessage; // Set to OS error message if process start failed. |
8 } | 8 } |
9 | 9 |
10 | 10 |
(...skipping 26 matching lines...) Expand all Loading... |
37 } | 37 } |
38 _workingDirectory = workingDirectory; | 38 _workingDirectory = workingDirectory; |
39 | 39 |
40 _in = new _Socket._internalReadOnly(); // stdout coming from process. | 40 _in = new _Socket._internalReadOnly(); // stdout coming from process. |
41 _out = new _Socket._internalWriteOnly(); // stdin going to process. | 41 _out = new _Socket._internalWriteOnly(); // stdin going to process. |
42 _err = new _Socket._internalReadOnly(); // stderr coming from process. | 42 _err = new _Socket._internalReadOnly(); // stderr coming from process. |
43 _exitHandler = new _Socket._internalReadOnly(); | 43 _exitHandler = new _Socket._internalReadOnly(); |
44 _closed = false; | 44 _closed = false; |
45 _killed = false; | 45 _killed = false; |
46 _started = false; | 46 _started = false; |
47 _exitHandlerCallback = null; | 47 _onExit = null; |
48 // TODO(ager): Make the actual process starting really async instead of | 48 // TODO(ager): Make the actual process starting really async instead of |
49 // simulating it with a timer. | 49 // simulating it with a timer. |
50 new Timer((Timer ignore) => start(), 0); | 50 new Timer((Timer ignore) => start(), 0); |
51 } | 51 } |
52 | 52 |
53 int _intFromBytes(List<int> bytes, int offset) { | 53 int _intFromBytes(List<int> bytes, int offset) { |
54 return (bytes[offset] + | 54 return (bytes[offset] + |
55 (bytes[offset + 1] << 8) + | 55 (bytes[offset + 1] << 8) + |
56 (bytes[offset + 2] << 16) + | 56 (bytes[offset + 2] << 16) + |
57 (bytes[offset + 3] << 24)); | 57 (bytes[offset + 3] << 24)); |
58 } | 58 } |
59 | 59 |
60 void start() { | 60 void start() { |
61 var status = new _ProcessStartStatus(); | 61 var status = new _ProcessStartStatus(); |
62 bool success = _start(_path, | 62 bool success = _start(_path, |
63 _arguments, | 63 _arguments, |
64 _workingDirectory, | 64 _workingDirectory, |
65 _in, | 65 _in, |
66 _out, | 66 _out, |
67 _err, | 67 _err, |
68 _exitHandler, | 68 _exitHandler, |
69 status); | 69 status); |
70 if (!success) { | 70 if (!success) { |
71 close(); | 71 close(); |
72 if (_errorHandler !== null) { | 72 if (_onError !== null) { |
73 _errorHandler(new ProcessException(status._errorMessage, | 73 _onError(new ProcessException(status._errorMessage, status._errorCode)); |
74 status._errorCode)); | |
75 return; | 74 return; |
76 } | 75 } |
77 } | 76 } |
78 _started = true; | 77 _started = true; |
79 | 78 |
80 // Make sure to activate socket handlers now that the file | 79 // Make sure to activate socket handlers now that the file |
81 // descriptors have been set. | 80 // descriptors have been set. |
82 _in._activateHandlers(); | 81 _in._activateHandlers(); |
83 _out._activateHandlers(); | 82 _out._activateHandlers(); |
84 _err._activateHandlers(); | 83 _err._activateHandlers(); |
85 | 84 |
86 // Setup an exit handler to handle internal cleanup and possible | 85 // Setup an exit handler to handle internal cleanup and possible |
87 // callback when a process terminates. | 86 // callback when a process terminates. |
88 int exitDataRead = 0; | 87 int exitDataRead = 0; |
89 final int EXIT_DATA_SIZE = 8; | 88 final int EXIT_DATA_SIZE = 8; |
90 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); | 89 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); |
91 _exitHandler.inputStream.dataHandler = () { | 90 _exitHandler.inputStream.onData = () { |
92 | 91 |
93 int exitCode(List<int> ints) { | 92 int exitCode(List<int> ints) { |
94 var code = _intFromBytes(ints, 0); | 93 var code = _intFromBytes(ints, 0); |
95 var negative = _intFromBytes(ints, 4); | 94 var negative = _intFromBytes(ints, 4); |
96 assert(negative == 0 || negative == 1); | 95 assert(negative == 0 || negative == 1); |
97 return (negative == 0) ? code : -code; | 96 return (negative == 0) ? code : -code; |
98 } | 97 } |
99 | 98 |
100 void handleExit() { | 99 void handleExit() { |
101 if (_exitHandlerCallback !== null) { | 100 if (_onExit !== null) { |
102 _exitHandlerCallback(exitCode(exitDataBuffer)); | 101 _onExit(exitCode(exitDataBuffer)); |
103 } | 102 } |
104 } | 103 } |
105 | 104 |
106 exitDataRead += _exitHandler.inputStream.readInto( | 105 exitDataRead += _exitHandler.inputStream.readInto( |
107 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); | 106 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); |
108 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); | 107 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); |
109 }; | 108 }; |
110 | 109 |
111 if (_startHandler !== null) { | 110 if (_onStart !== null) { |
112 _startHandler(); | 111 _onStart(); |
113 } | 112 } |
114 } | 113 } |
115 | 114 |
116 bool _start(String path, | 115 bool _start(String path, |
117 List<String> arguments, | 116 List<String> arguments, |
118 String workingDirectory, | 117 String workingDirectory, |
119 Socket input, | 118 Socket input, |
120 Socket output, | 119 Socket output, |
121 Socket error, | 120 Socket error, |
122 Socket exitHandler, | 121 Socket exitHandler, |
(...skipping 15 matching lines...) Expand all Loading... |
138 | 137 |
139 OutputStream get stdin() { | 138 OutputStream get stdin() { |
140 if (_closed) { | 139 if (_closed) { |
141 throw new ProcessException("Process closed"); | 140 throw new ProcessException("Process closed"); |
142 } | 141 } |
143 return _out.outputStream; | 142 return _out.outputStream; |
144 } | 143 } |
145 | 144 |
146 void kill() { | 145 void kill() { |
147 if (_closed && _pid === null) { | 146 if (_closed && _pid === null) { |
148 if (_errorHandler !== null) { | 147 if (_onError !== null) { |
149 _errorHandler(new ProcessException("Process closed")); | 148 _onError(new ProcessException("Process closed")); |
150 } | 149 } |
151 return; | 150 return; |
152 } | 151 } |
153 if (_killed) { | 152 if (_killed) { |
154 return; | 153 return; |
155 } | 154 } |
156 // TODO(ager): Make the actual kill operation asynchronous. | 155 // TODO(ager): Make the actual kill operation asynchronous. |
157 if (_kill(_pid)) { | 156 if (_kill(_pid)) { |
158 _killed = true; | 157 _killed = true; |
159 return; | 158 return; |
160 } | 159 } |
161 if (_errorHandler !== null) { | 160 if (_onError !== null) { |
162 _errorHandler(new ProcessException("Could not kill process")); | 161 _onError(new ProcessException("Could not kill process")); |
163 return; | 162 return; |
164 } | 163 } |
165 } | 164 } |
166 | 165 |
167 void _kill(int pid) native "Process_Kill"; | 166 void _kill(int pid) native "Process_Kill"; |
168 | 167 |
169 void close() { | 168 void close() { |
170 if (_closed) { | 169 if (_closed) { |
171 throw new ProcessException("Process closed"); | 170 throw new ProcessException("Process closed"); |
172 } | 171 } |
173 _in.close(); | 172 _in.close(); |
174 _out.close(); | 173 _out.close(); |
175 _err.close(); | 174 _err.close(); |
176 _exitHandler.close(); | 175 _exitHandler.close(); |
177 _closed = true; | 176 _closed = true; |
178 } | 177 } |
179 | 178 |
180 void set exitHandler(void callback(int exitCode)) { | 179 void set onExit(void callback(int exitCode)) { |
181 if (_closed) { | 180 if (_closed) { |
182 throw new ProcessException("Process closed"); | 181 throw new ProcessException("Process closed"); |
183 } | 182 } |
184 if (_killed) { | 183 if (_killed) { |
185 throw new ProcessException("Process killed"); | 184 throw new ProcessException("Process killed"); |
186 } | 185 } |
187 _exitHandlerCallback = callback; | 186 _onExit = callback; |
188 } | 187 } |
189 | 188 |
190 void set errorHandler(void callback(ProcessException exception)) { | 189 void set onError(void callback(ProcessException exception)) { |
191 _errorHandler = callback; | 190 _onError = callback; |
192 } | 191 } |
193 | 192 |
194 void set startHandler(void callback()) { | 193 void set onStart(void callback()) { |
195 _startHandler = callback; | 194 _onStart = callback; |
196 } | 195 } |
197 | 196 |
198 String _path; | 197 String _path; |
199 ObjectArray<String> _arguments; | 198 ObjectArray<String> _arguments; |
200 String _workingDirectory; | 199 String _workingDirectory; |
201 Socket _in; | 200 Socket _in; |
202 Socket _out; | 201 Socket _out; |
203 Socket _err; | 202 Socket _err; |
204 Socket _exitHandler; | 203 Socket _exitHandler; |
205 int _pid; | 204 int _pid; |
206 bool _closed; | 205 bool _closed; |
207 bool _killed; | 206 bool _killed; |
208 bool _started; | 207 bool _started; |
209 Function _exitHandlerCallback; | 208 Function _onExit; |
210 Function _errorHandler; | 209 Function _onError; |
211 Function _startHandler; | 210 Function _onStart; |
212 } | 211 } |
OLD | NEW |