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 _onExit = null; | 47 _exitHandlerCallback = 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 (_onError !== null) { | 72 if (_errorHandler !== null) { |
73 _onError(new ProcessException(status._errorMessage, status._errorCode)); | 73 _errorHandler(new ProcessException(status._errorMessage, |
| 74 status._errorCode)); |
74 return; | 75 return; |
75 } | 76 } |
76 } | 77 } |
77 _started = true; | 78 _started = true; |
78 | 79 |
79 // Make sure to activate socket handlers now that the file | 80 // Make sure to activate socket handlers now that the file |
80 // descriptors have been set. | 81 // descriptors have been set. |
81 _in._activateHandlers(); | 82 _in._activateHandlers(); |
82 _out._activateHandlers(); | 83 _out._activateHandlers(); |
83 _err._activateHandlers(); | 84 _err._activateHandlers(); |
84 | 85 |
85 // Setup an exit handler to handle internal cleanup and possible | 86 // Setup an exit handler to handle internal cleanup and possible |
86 // callback when a process terminates. | 87 // callback when a process terminates. |
87 int exitDataRead = 0; | 88 int exitDataRead = 0; |
88 final int EXIT_DATA_SIZE = 8; | 89 final int EXIT_DATA_SIZE = 8; |
89 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); | 90 List<int> exitDataBuffer = new List<int>(EXIT_DATA_SIZE); |
90 _exitHandler.inputStream.onData = () { | 91 _exitHandler.inputStream.dataHandler = () { |
91 | 92 |
92 int exitCode(List<int> ints) { | 93 int exitCode(List<int> ints) { |
93 var code = _intFromBytes(ints, 0); | 94 var code = _intFromBytes(ints, 0); |
94 var negative = _intFromBytes(ints, 4); | 95 var negative = _intFromBytes(ints, 4); |
95 assert(negative == 0 || negative == 1); | 96 assert(negative == 0 || negative == 1); |
96 return (negative == 0) ? code : -code; | 97 return (negative == 0) ? code : -code; |
97 } | 98 } |
98 | 99 |
99 void handleExit() { | 100 void handleExit() { |
100 if (_onExit !== null) { | 101 if (_exitHandlerCallback !== null) { |
101 _onExit(exitCode(exitDataBuffer)); | 102 _exitHandlerCallback(exitCode(exitDataBuffer)); |
102 } | 103 } |
103 } | 104 } |
104 | 105 |
105 exitDataRead += _exitHandler.inputStream.readInto( | 106 exitDataRead += _exitHandler.inputStream.readInto( |
106 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); | 107 exitDataBuffer, exitDataRead, EXIT_DATA_SIZE - exitDataRead); |
107 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); | 108 if (exitDataRead == EXIT_DATA_SIZE) handleExit(); |
108 }; | 109 }; |
109 | 110 |
110 if (_onStart !== null) { | 111 if (_startHandler !== null) { |
111 _onStart(); | 112 _startHandler(); |
112 } | 113 } |
113 } | 114 } |
114 | 115 |
115 bool _start(String path, | 116 bool _start(String path, |
116 List<String> arguments, | 117 List<String> arguments, |
117 String workingDirectory, | 118 String workingDirectory, |
118 Socket input, | 119 Socket input, |
119 Socket output, | 120 Socket output, |
120 Socket error, | 121 Socket error, |
121 Socket exitHandler, | 122 Socket exitHandler, |
(...skipping 15 matching lines...) Expand all Loading... |
137 | 138 |
138 OutputStream get stdin() { | 139 OutputStream get stdin() { |
139 if (_closed) { | 140 if (_closed) { |
140 throw new ProcessException("Process closed"); | 141 throw new ProcessException("Process closed"); |
141 } | 142 } |
142 return _out.outputStream; | 143 return _out.outputStream; |
143 } | 144 } |
144 | 145 |
145 void kill() { | 146 void kill() { |
146 if (_closed && _pid === null) { | 147 if (_closed && _pid === null) { |
147 if (_onError !== null) { | 148 if (_errorHandler !== null) { |
148 _onError(new ProcessException("Process closed")); | 149 _errorHandler(new ProcessException("Process closed")); |
149 } | 150 } |
150 return; | 151 return; |
151 } | 152 } |
152 if (_killed) { | 153 if (_killed) { |
153 return; | 154 return; |
154 } | 155 } |
155 // TODO(ager): Make the actual kill operation asynchronous. | 156 // TODO(ager): Make the actual kill operation asynchronous. |
156 if (_kill(_pid)) { | 157 if (_kill(_pid)) { |
157 _killed = true; | 158 _killed = true; |
158 return; | 159 return; |
159 } | 160 } |
160 if (_onError !== null) { | 161 if (_errorHandler !== null) { |
161 _onError(new ProcessException("Could not kill process")); | 162 _errorHandler(new ProcessException("Could not kill process")); |
162 return; | 163 return; |
163 } | 164 } |
164 } | 165 } |
165 | 166 |
166 void _kill(int pid) native "Process_Kill"; | 167 void _kill(int pid) native "Process_Kill"; |
167 | 168 |
168 void close() { | 169 void close() { |
169 if (_closed) { | 170 if (_closed) { |
170 throw new ProcessException("Process closed"); | 171 throw new ProcessException("Process closed"); |
171 } | 172 } |
172 _in.close(); | 173 _in.close(); |
173 _out.close(); | 174 _out.close(); |
174 _err.close(); | 175 _err.close(); |
175 _exitHandler.close(); | 176 _exitHandler.close(); |
176 _closed = true; | 177 _closed = true; |
177 } | 178 } |
178 | 179 |
179 void set onExit(void callback(int exitCode)) { | 180 void set exitHandler(void callback(int exitCode)) { |
180 if (_closed) { | 181 if (_closed) { |
181 throw new ProcessException("Process closed"); | 182 throw new ProcessException("Process closed"); |
182 } | 183 } |
183 if (_killed) { | 184 if (_killed) { |
184 throw new ProcessException("Process killed"); | 185 throw new ProcessException("Process killed"); |
185 } | 186 } |
186 _onExit = callback; | 187 _exitHandlerCallback = callback; |
187 } | 188 } |
188 | 189 |
189 void set onError(void callback(ProcessException exception)) { | 190 void set errorHandler(void callback(ProcessException exception)) { |
190 _onError = callback; | 191 _errorHandler = callback; |
191 } | 192 } |
192 | 193 |
193 void set onStart(void callback()) { | 194 void set startHandler(void callback()) { |
194 _onStart = callback; | 195 _startHandler = callback; |
195 } | 196 } |
196 | 197 |
197 String _path; | 198 String _path; |
198 ObjectArray<String> _arguments; | 199 ObjectArray<String> _arguments; |
199 String _workingDirectory; | 200 String _workingDirectory; |
200 Socket _in; | 201 Socket _in; |
201 Socket _out; | 202 Socket _out; |
202 Socket _err; | 203 Socket _err; |
203 Socket _exitHandler; | 204 Socket _exitHandler; |
204 int _pid; | 205 int _pid; |
205 bool _closed; | 206 bool _closed; |
206 bool _killed; | 207 bool _killed; |
207 bool _started; | 208 bool _started; |
208 Function _onExit; | 209 Function _exitHandlerCallback; |
209 Function _onError; | 210 Function _errorHandler; |
210 Function _onStart; | 211 Function _startHandler; |
211 } | 212 } |
OLD | NEW |