117 ! ! |
123 ! ! |
118 |
124 |
119 !GDBDebugger methodsFor:'commands'! |
125 !GDBDebugger methodsFor:'commands'! |
120 |
126 |
121 send: command |
127 send: command |
122 "Execute given `command` and wait until it finishes. |
128 "Execute given `command` and wait until it finishes and return its result. |
123 Command can be either an instance of GDBCommand or |
129 `command` may be either a GDBCommand or string, in which case it will |
124 a String. If String, it is assumed to be a CLI command |
130 be parsed into a GDBCommand. |
125 string. |
131 " |
126 " |
132 ^ self send:command andWait:true. |
127 ^ self send: command wait: true. |
|
128 |
133 |
129 "Created: / 03-06-2014 / 00:10:38 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
134 "Created: / 03-06-2014 / 00:10:38 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
130 "Modified (comment): / 28-02-2015 / 00:40:32 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
135 "Modified (comment): / 08-03-2015 / 05:50:46 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
131 ! |
136 ! |
132 |
137 |
133 send: command wait: wait |
138 send:command andWait:wait |
134 "Sends given `command` to GDB. If `aBoolean` is true, wait for |
139 "Sends given `command` to GDB. If `wait` is true, wait for |
135 command to finish. Otherwise, return immediately." |
140 command to finish and return the command result. |
136 |
141 Otherwise, return nil immediately. |
137 | cmd token blocker handler1 handler2 result | |
142 |
|
143 `command` may be either a GDBCommand or string, in which case it will |
|
144 be parsed into a GDBCommand. |
|
145 " |
|
146 |
|
147 | cmd token blocker handler1 handler2 result | |
138 |
148 |
139 cmd := command. |
149 cmd := command. |
140 cmd isString ifTrue:[ |
150 cmd isString ifTrue:[ |
141 cmd := GDBCLICommand new value: cmd. |
151 cmd := GDBCLICommand new value:cmd. |
142 ]. |
152 ]. |
143 (wait and:[Processor activeProcess == connection eventDispatchProcess]) ifTrue:[ |
|
144 self error: 'Cannot send commands from within event dispatching process. Would deadlock'. |
|
145 ]. |
|
146 |
|
147 token := self nextCommandSequnceNumber. |
153 token := self nextCommandSequnceNumber. |
148 cmd token: token. |
154 cmd token:token. |
149 ^ wait ifTrue:[ |
155 ^ wait ifTrue:[ |
150 handler1 := [ :ev | |
156 self assert:Processor activeProcess ~~ connection eventDispatchProcess |
151 ev token == token ifTrue:[ |
157 message:'Cannot send commands from within event dispatching process. Would deadlock'. |
152 connection eventAnnouncer unsubscribe: handler1. |
158 handler1 := [:ev | |
153 result := ev result. |
159 ev token == token ifTrue:[ |
154 connection eventAnnouncerInternal when: GDBEventSetProcessingFinished do: handler2. |
160 connection eventAnnouncer unsubscribe:handler1. |
155 ]]. |
161 result := ev result. |
156 handler2 := [ :ev | |
162 connection eventAnnouncerInternal when:GDBEventSetProcessingFinished |
157 connection eventAnnouncerInternal unsubscribe: handler2. |
163 do:handler2. |
158 blocker signal. |
164 ] |
159 ]. |
165 ]. |
|
166 handler2 := [:ev | |
|
167 connection eventAnnouncerInternal unsubscribe:handler2. |
|
168 blocker signal. |
|
169 ]. |
160 blocker := Semaphore new. |
170 blocker := Semaphore new. |
161 connection eventAnnouncer when: GDBCommandResultEvent do: handler1. |
171 connection eventAnnouncer when:GDBCommandResultEvent do:handler1. |
162 connection pushEvent: (GDBCommandEvent new command: cmd). |
172 connection pushEvent:(GDBCommandEvent new command:cmd). |
163 blocker wait. |
173 blocker wait. |
164 result. |
174 result. |
165 ] ifFalse:[ |
175 ] |
166 connection pushEvent: (GDBCommandEvent new command: cmd). |
176 ifFalse:[ |
|
177 connection pushEvent:(GDBCommandEvent new command:cmd). |
167 nil. |
178 nil. |
168 ] |
179 ] |
169 |
180 |
170 "Created: / 02-06-2014 / 23:45:43 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
181 "Created: / 02-06-2014 / 23:45:43 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
171 "Modified: / 28-02-2015 / 00:42:40 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
182 "Modified: / 08-03-2015 / 05:51:52 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
183 ! |
|
184 |
|
185 send:command andWaitFor:eventHandlers |
|
186 "Sends given `command` to GDB and then wait for events mathing |
|
187 `eventHandlers`. |
|
188 |
|
189 Params: |
|
190 `command` may be either a GDBCommand or string, in which case it will |
|
191 be parsed into a GDBCommand. |
|
192 `eventHandler` may be either nil or event class or one arg block or collection |
|
193 of event classes or blocks. |
|
194 - If nil then do not wait for anything (use nil for async send) |
|
195 - If event class, then wait for an event of that class. Note, that |
|
196 subclasses are handled too. |
|
197 - If block, then wait for an event for which the block returns true. |
|
198 - If collectio, then wait for a sequence of events, each matched as above. |
|
199 |
|
200 Returns: a matching event or events (in case a collection of handlers has been passes)" |
|
201 |
|
202 ^ self send: command andWaitFor: eventHandlers withTimeoutMs: nil |
|
203 |
|
204 "Created: / 08-03-2015 / 06:03:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
205 ! |
|
206 |
|
207 send:command andWaitFor:eventHandlers withTimeoutMs:timeout |
|
208 "Sends given `command` to GDB and then wait for events mathing |
|
209 `eventHandlers`. Raise a TimeoutError if expected events don't arrive |
|
210 in specified time. |
|
211 |
|
212 Params: |
|
213 `command` may be either a GDBCommand or string, in which case it will |
|
214 be parsed into a GDBCommand. |
|
215 `eventHandler` may be either nil or event class or one arg block or collection |
|
216 of event classes or blocks. |
|
217 - If nil then do not wait for anything (use nil for async send) |
|
218 - If event class, then wait for an event of that class. Note, that |
|
219 subclasses are handled too. |
|
220 - If block, then wait for an event for which the block returns true. |
|
221 - If collectio, then wait for a sequence of events, each matched as above. |
|
222 `timeout` wait at most that much milliseconds, throw TimeoutError otherwise. If `timeout` == mil |
|
223 then wait for indefinitly |
|
224 |
|
225 Returns: a matching event or events (in case a collection of handlers has been passes)" |
|
226 |
|
227 | commandObject | |
|
228 |
|
229 command isString ifTrue:[ |
|
230 commandObject := (GDBMIParser on:command) parseCommand. |
|
231 commandObject token:self nextCommandSequnceNumber. |
|
232 ] ifFalse:[ |
|
233 commandObject := command. |
|
234 commandObject token isNil ifTrue:[ |
|
235 commandObject token:self nextCommandSequnceNumber. |
|
236 ]. |
|
237 ]. |
|
238 ^ self |
|
239 do:[ connection pushEvent:(GDBCommandEvent new command: commandObject) ] |
|
240 andWaitFor: eventHandlers |
|
241 withTimeoutMs: timeout |
|
242 |
|
243 "Created: / 07-03-2015 / 11:38:45 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
244 "Modified: / 08-03-2015 / 07:31:15 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
245 ! ! |
|
246 |
|
247 !GDBDebugger methodsFor:'commands-convenience'! |
|
248 |
|
249 do: block andWaitFor:eventHandlers |
|
250 "Evaluates a given block and then wait for events. |
|
251 `eventHandlers`. |
|
252 Params: |
|
253 `block` block to evaluate |
|
254 `eventHandler` may be either nil or event class or one arg block or collection |
|
255 of event classes or blocks. |
|
256 - If nil then do not wait for anything (use nil for async send) |
|
257 - If event class, then wait for an event of that class. Note, that |
|
258 subclasses are handled too. |
|
259 - If block, then wait for an event for which the block returns true. |
|
260 - If collectio, then wait for a sequence of events, each matched as above. |
|
261 Returns: a matching event or events (in case a collection of handlers has been passed)" |
|
262 |
|
263 ^ self do: block andWaitFor: eventHandlers withTimeoutMs: nil |
|
264 |
|
265 "Created: / 08-03-2015 / 07:30:36 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
266 ! |
|
267 |
|
268 do: block andWaitFor:eventHandlers withTimeoutMs:timeout |
|
269 "Evaluates a given block and then wait for events. |
|
270 `eventHandlers`. Raise a TimeoutError if expected events don't arrive |
|
271 in specified time. |
|
272 |
|
273 Params: |
|
274 `block` block to evaluate |
|
275 `eventHandler` may be either nil or event class or one arg block or collection |
|
276 of event classes or blocks. |
|
277 - If nil then do not wait for anything (use nil for async send) |
|
278 - If event class, then wait for an event of that class. Note, that |
|
279 subclasses are handled too. |
|
280 - If block, then wait for an event for which the block returns true. |
|
281 - If collectio, then wait for a sequence of events, each matched as above. |
|
282 `timeout` wait at most that much milliseconds, throw TimeoutError otherwise. If `timeout` == mil |
|
283 then wait for indefinitly |
|
284 |
|
285 Returns: a matching event or events (in case a collection of handlers has been passes)" |
|
286 |
|
287 | handlersArray handlerFinal eventsArray blocker | |
|
288 |
|
289 eventHandlers isNil ifTrue:[ |
|
290 "/ Asynchronous send... |
|
291 self assert:timeout isNil. |
|
292 block value. |
|
293 ^ nil |
|
294 ]. |
|
295 "/ Synchronous send... |
|
296 self assert:Processor activeProcess ~~ connection eventDispatchProcess |
|
297 message:'Cannot send commands from within event dispatching process. Would deadlock'. |
|
298 eventHandlers isCollection |
|
299 ifTrue:[ handlersArray := eventHandlers ] |
|
300 ifFalse:[ handlersArray := Array with:eventHandlers ]. |
|
301 eventsArray := Array new:handlersArray size. |
|
302 1 to:handlersArray size do:[:i | |
|
303 | handler | |
|
304 |
|
305 handler := handlersArray at:i. |
|
306 handlersArray at:i |
|
307 put:[:event | |
|
308 | matches | |
|
309 |
|
310 matches := handler isBlock ifTrue:[ handler value:event ] ifFalse:[ event isKindOf:handler ]. |
|
311 (matches and:[ i == 1 or:[ (eventsArray at:i - 1) notNil ] ]) ifTrue:[ |
|
312 eventsArray at:i put:event. |
|
313 self announcer unsubscribe:(handlersArray at:i). |
|
314 i == handlersArray size ifTrue:[ |
|
315 connection eventAnnouncerInternal when: GDBEventSetProcessingFinished do: handlerFinal. |
|
316 ]. |
|
317 ]. |
|
318 ]. |
|
319 self announcer when:GDBEvent do:(handlersArray at:i). |
|
320 ]. |
|
321 handlerFinal := [ :event | connection eventAnnouncerInternal unsubscribe: handlerFinal. blocker signal ]. |
|
322 blocker := Semaphore new. |
|
323 block value. |
|
324 [ |
|
325 (blocker waitWithTimeoutMs:timeout) isNil ifTrue:[ |
|
326 eventsArray := nil. |
|
327 ]. |
|
328 ] ensure:[ |
|
329 handlersArray do:[:handler | |
|
330 handler notNil ifTrue:[ |
|
331 self announcer unsubscribe:handler |
|
332 ] |
|
333 ]. |
|
334 ]. |
|
335 eventsArray isNil ifTrue:[ |
|
336 (TimeoutError newException) |
|
337 parameter:timeout; |
|
338 raise. |
|
339 ]. |
|
340 ^ eventHandlers isCollection ifTrue:[ eventsArray ] ifFalse:[ eventsArray first ] |
|
341 |
|
342 "Created: / 08-03-2015 / 07:28:39 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
172 ! ! |
343 ! ! |
173 |
344 |
174 !GDBDebugger methodsFor:'event handling'! |
345 !GDBDebugger methodsFor:'event handling'! |
175 |
346 |
176 onCommandEvent:aGDBCommandEvent |
347 onCommandEvent:aGDBCommandEvent |