@@ -9,10 +9,12 @@ class TestGdbRemoteFork(gdbremote_testcase.GdbRemoteTestCaseBase):
9
9
10
10
fork_regex = ("[$]T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
11
11
"{}:p([0-9a-f]+)[.]([0-9a-f]+).*" )
12
+ fork_regex_nonstop = ("%Stop:T05thread:p([0-9a-f]+)[.]([0-9a-f]+);.*"
13
+ "{}:p([0-9a-f]+)[.]([0-9a-f]+).*" )
12
14
fork_capture = {1 : "parent_pid" , 2 : "parent_tid" ,
13
15
3 : "child_pid" , 4 : "child_tid" }
14
16
15
- def start_fork_test (self , args , variant = "fork" ):
17
+ def start_fork_test (self , args , variant = "fork" , nonstop = False ):
16
18
self .build ()
17
19
self .prep_debug_monitor_and_inferior (inferior_args = args )
18
20
self .add_qSupported_packets (["multiprocess+" ,
@@ -22,11 +24,24 @@ def start_fork_test(self, args, variant="fork"):
22
24
self .reset_test_sequence ()
23
25
24
26
# continue and expect fork
25
- self .test_sequence .add_log_lines ([
26
- "read packet: $c#00" ,
27
- {"direction" : "send" , "regex" : self .fork_regex .format (variant ),
28
- "capture" : self .fork_capture },
29
- ], True )
27
+ if nonstop :
28
+ self .test_sequence .add_log_lines ([
29
+ "read packet: $QNonStop:1#00" ,
30
+ "send packet: $OK#00" ,
31
+ "read packet: $c#00" ,
32
+ "send packet: $OK#00" ,
33
+ {"direction" : "send" ,
34
+ "regex" : self .fork_regex_nonstop .format (variant ),
35
+ "capture" : self .fork_capture },
36
+ "read packet: $vStopped#00" ,
37
+ "send packet: $OK#00" ,
38
+ ], True )
39
+ else :
40
+ self .test_sequence .add_log_lines ([
41
+ "read packet: $c#00" ,
42
+ {"direction" : "send" , "regex" : self .fork_regex .format (variant ),
43
+ "capture" : self .fork_capture },
44
+ ], True )
30
45
ret = self .expect_gdbremote_sequence ()
31
46
self .reset_test_sequence ()
32
47
@@ -45,9 +60,9 @@ def test_fork_multithreaded(self):
45
60
], True )
46
61
self .expect_gdbremote_sequence ()
47
62
48
- def fork_and_detach_test (self , variant ):
63
+ def fork_and_detach_test (self , variant , nonstop = False ):
49
64
parent_pid , parent_tid , child_pid , child_tid = (
50
- self .start_fork_test ([variant ], variant ))
65
+ self .start_fork_test ([variant ], variant , nonstop = nonstop ))
51
66
52
67
# detach the forked child
53
68
self .test_sequence .add_log_lines ([
@@ -77,6 +92,20 @@ def test_fork(self):
77
92
], True )
78
93
self .expect_gdbremote_sequence ()
79
94
95
+ @add_test_categories (["fork" ])
96
+ def test_fork_nonstop (self ):
97
+ parent_pid , _ = self .fork_and_detach_test ("fork" , nonstop = True )
98
+
99
+ # resume the parent
100
+ self .test_sequence .add_log_lines ([
101
+ "read packet: $c#00" ,
102
+ "send packet: $OK#00" ,
103
+ "send packet: %Stop:W00;process:{}#00" .format (parent_pid ),
104
+ "read packet: $vStopped#00" ,
105
+ "send packet: $OK#00" ,
106
+ ], True )
107
+ self .expect_gdbremote_sequence ()
108
+
80
109
@add_test_categories (["fork" ])
81
110
def test_vfork (self ):
82
111
parent_pid , parent_tid = self .fork_and_detach_test ("vfork" )
@@ -93,9 +122,32 @@ def test_vfork(self):
93
122
], True )
94
123
self .expect_gdbremote_sequence ()
95
124
96
- def fork_and_follow_test (self , variant ):
125
+ @add_test_categories (["fork" ])
126
+ def test_vfork_nonstop (self ):
127
+ parent_pid , parent_tid = self .fork_and_detach_test ("vfork" ,
128
+ nonstop = True )
129
+
130
+ # resume the parent
131
+ self .test_sequence .add_log_lines ([
132
+ "read packet: $c#00" ,
133
+ "send packet: $OK#00" ,
134
+ {"direction" : "send" ,
135
+ "regex" : r"%Stop:T05thread:p{}[.]{}.*vforkdone.*" .format (
136
+ parent_pid , parent_tid ),
137
+ },
138
+ "read packet: $vStopped#00" ,
139
+ "send packet: $OK#00" ,
140
+ "read packet: $c#00" ,
141
+ "send packet: $OK#00" ,
142
+ "send packet: %Stop:W00;process:{}#00" .format (parent_pid ),
143
+ "read packet: $vStopped#00" ,
144
+ "send packet: $OK#00" ,
145
+ ], True )
146
+ self .expect_gdbremote_sequence ()
147
+
148
+ def fork_and_follow_test (self , variant , nonstop = False ):
97
149
parent_pid , parent_tid , child_pid , child_tid = (
98
- self .start_fork_test ([variant ], variant ))
150
+ self .start_fork_test ([variant ], variant , nonstop = nonstop ))
99
151
100
152
# switch to the forked child
101
153
self .test_sequence .add_log_lines ([
@@ -113,18 +165,37 @@ def fork_and_follow_test(self, variant):
113
165
"send packet: $OK#00" ,
114
166
# then resume the child
115
167
"read packet: $c#00" ,
116
- "send packet: $W00;process:{}#00" .format (child_pid ),
117
168
], True )
169
+
170
+ if nonstop :
171
+ self .test_sequence .add_log_lines ([
172
+ "send packet: $OK#00" ,
173
+ "send packet: %Stop:W00;process:{}#00" .format (child_pid ),
174
+ "read packet: $vStopped#00" ,
175
+ "send packet: $OK#00" ,
176
+ ], True )
177
+ else :
178
+ self .test_sequence .add_log_lines ([
179
+ "send packet: $W00;process:{}#00" .format (child_pid ),
180
+ ], True )
118
181
self .expect_gdbremote_sequence ()
119
182
120
183
@add_test_categories (["fork" ])
121
184
def test_fork_follow (self ):
122
185
self .fork_and_follow_test ("fork" )
123
186
187
+ @add_test_categories (["fork" ])
188
+ def test_fork_follow_nonstop (self ):
189
+ self .fork_and_follow_test ("fork" , nonstop = True )
190
+
124
191
@add_test_categories (["fork" ])
125
192
def test_vfork_follow (self ):
126
193
self .fork_and_follow_test ("vfork" )
127
194
195
+ @add_test_categories (["fork" ])
196
+ def test_vfork_follow_nonstop (self ):
197
+ self .fork_and_follow_test ("vfork" , nonstop = True )
198
+
128
199
@add_test_categories (["fork" ])
129
200
def test_select_wrong_pid (self ):
130
201
self .build ()
@@ -191,10 +262,9 @@ def test_detach_current(self):
191
262
], True )
192
263
self .expect_gdbremote_sequence ()
193
264
194
- @add_test_categories (["fork" ])
195
- def test_detach_all (self ):
265
+ def detach_all_test (self , nonstop = False ):
196
266
parent_pid , parent_tid , child_pid , child_tid = (
197
- self .start_fork_test (["fork" ]))
267
+ self .start_fork_test (["fork" ], nonstop = nonstop ))
198
268
199
269
self .test_sequence .add_log_lines ([
200
270
# double-check our PIDs
@@ -213,6 +283,14 @@ def test_detach_all(self):
213
283
], True )
214
284
self .expect_gdbremote_sequence ()
215
285
286
+ @add_test_categories (["fork" ])
287
+ def test_detach_all (self ):
288
+ self .detach_all_test ()
289
+
290
+ @add_test_categories (["fork" ])
291
+ def test_detach_all_nonstop (self ):
292
+ self .detach_all_test (nonstop = True )
293
+
216
294
@add_test_categories (["fork" ])
217
295
def test_kill_all (self ):
218
296
parent_pid , _ , child_pid , _ = self .start_fork_test (["fork" ])
@@ -230,10 +308,51 @@ def test_kill_all(self):
230
308
self .assertEqual (set ([ret ["pid1" ], ret ["pid2" ]]),
231
309
set ([parent_pid , child_pid ]))
232
310
233
- def vkill_test (self , kill_parent = False , kill_child = False ):
311
+ @add_test_categories (["fork" ])
312
+ def test_kill_all_nonstop (self ):
313
+ parent_pid , _ , child_pid , _ = self .start_fork_test (["fork" ],
314
+ nonstop = True )
315
+
316
+ exit_regex = "X09;process:([0-9a-f]+)"
317
+ # Depending on a potential race, the second kill may make it into
318
+ # the async queue before we issue vStopped or after. In the former
319
+ # case, we should expect the exit status in reply to vStopped.
320
+ # In the latter, we should expect an OK response (queue empty),
321
+ # followed by another async notification.
322
+ vstop_regex = "[$](OK|{})#.*" .format (exit_regex )
323
+ self .test_sequence .add_log_lines ([
324
+ # kill all processes
325
+ "read packet: $k#00" ,
326
+ "send packet: $OK#00" ,
327
+ {"direction" : "send" , "regex" : "%Stop:{}#.*" .format (exit_regex ),
328
+ "capture" : {1 : "pid1" }},
329
+ "read packet: $vStopped#00" ,
330
+ {"direction" : "send" , "regex" : vstop_regex ,
331
+ "capture" : {1 : "vstop_reply" , 2 : "pid2" }},
332
+ ], True )
333
+ ret = self .expect_gdbremote_sequence ()
334
+ pid1 = ret ["pid1" ]
335
+ if ret ["vstop_reply" ] == "OK" :
336
+ self .reset_test_sequence ()
337
+ self .test_sequence .add_log_lines ([
338
+ {"direction" : "send" , "regex" : "%Stop:{}#.*" .format (exit_regex ),
339
+ "capture" : {1 : "pid2" }},
340
+ ], True )
341
+ ret = self .expect_gdbremote_sequence ()
342
+ pid2 = ret ["pid2" ]
343
+ self .reset_test_sequence ()
344
+ self .test_sequence .add_log_lines ([
345
+ "read packet: $vStopped#00" ,
346
+ "send packet: $OK#00" ,
347
+ ], True )
348
+ self .expect_gdbremote_sequence ()
349
+ self .assertEqual (set ([ret ["pid1" ], ret ["pid2" ]]),
350
+ set ([parent_pid , child_pid ]))
351
+
352
+ def vkill_test (self , kill_parent = False , kill_child = False , nonstop = False ):
234
353
assert kill_parent or kill_child
235
354
parent_pid , parent_tid , child_pid , child_tid = (
236
- self .start_fork_test (["fork" ]))
355
+ self .start_fork_test (["fork" ], nonstop = nonstop ))
237
356
238
357
if kill_parent :
239
358
self .test_sequence .add_log_lines ([
@@ -269,6 +388,10 @@ def test_vkill_parent(self):
269
388
def test_vkill_both (self ):
270
389
self .vkill_test (kill_parent = True , kill_child = True )
271
390
391
+ @add_test_categories (["fork" ])
392
+ def test_vkill_both_nonstop (self ):
393
+ self .vkill_test (kill_parent = True , kill_child = True , nonstop = True )
394
+
272
395
def resume_one_test (self , run_order , use_vCont = False ):
273
396
parent_pid , parent_tid , child_pid , child_tid = (
274
397
self .start_fork_test (["fork" , "trap" ]))
0 commit comments