|
30 | 30 | # MAX_SAMPLES_SAVED is the maximum number of samples saved. |
31 | 31 | MAX_SAMPLES_SAVED = 500 |
32 | 32 |
|
| 33 | +def stop_process(child_process, timeout=30, poll_interval=0.2): |
| 34 | + """ |
| 35 | + Stops a pexpect child process using SIGINT (Ctrl+C), |
| 36 | + and forcefully terminates it if it doesn't exit within the timeout. |
| 37 | +
|
| 38 | + Parameters: |
| 39 | + child_process (pexpect.spawn): The process to stop. |
| 40 | + timeout (int): Max time (in seconds) to wait for graceful exit. |
| 41 | + poll_interval (float): Time between checks in seconds. |
| 42 | +
|
| 43 | + Returns: |
| 44 | + bool: True if process exited gracefully, False if it was killed. |
| 45 | + """ |
| 46 | + if child_process.isalive(): |
| 47 | + try: |
| 48 | + child_process.sendintr() |
| 49 | + except Exception as e: |
| 50 | + return True # Process already exited |
| 51 | + else: |
| 52 | + return True # Process already exited |
| 53 | + |
| 54 | + start_time = time.time() |
| 55 | + |
| 56 | + while child_process.isalive() and (time.time() - start_time < timeout): |
| 57 | + time.sleep(poll_interval) |
| 58 | + |
| 59 | + if child_process.isalive(): |
| 60 | + child_process.terminate(force=True) |
| 61 | + return False # Process was forcefully terminated |
| 62 | + |
| 63 | + return True |
| 64 | + |
33 | 65 | def run_subscriber_shape_main( |
34 | 66 | name_executable: str, |
35 | 67 | parameters: str, |
@@ -165,11 +197,13 @@ def run_subscriber_shape_main( |
165 | 197 | log_message(f'Subscriber {subscriber_index}: Waiting for Publishers to ' |
166 | 198 | 'finish', verbosity) |
167 | 199 | for element in publishers_finished: |
168 | | - element.wait() # wait for all publishers to finish |
169 | | - # Send SIGINT to nicely close the application |
170 | | - if child_sub.isalive(): |
171 | | - child_sub.sendintr() |
172 | | - child_sub.wait() |
| 200 | + element.wait() # wait for all publishers to finish |
| 201 | + # Stop process |
| 202 | + if not stop_process(child_sub): |
| 203 | + log_message(f'Subscriber {subscriber_index} process did not exit ' |
| 204 | + 'gracefully; it was forcefully terminated.', |
| 205 | + verbosity) |
| 206 | + |
173 | 207 | return |
174 | 208 |
|
175 | 209 |
|
@@ -332,10 +366,12 @@ def run_publisher_shape_main( |
332 | 366 | for element in subscribers_finished: |
333 | 367 | element.wait() # wait for all subscribers to finish |
334 | 368 | publisher_finished.set() # set publisher as finished |
335 | | - # Send SIGINT to nicely close the application |
336 | | - if child_pub.isalive(): |
337 | | - child_pub.sendintr() |
338 | | - child_pub.wait() |
| 369 | + # Stop process |
| 370 | + if not stop_process(child_pub): |
| 371 | + log_message(f'Publisher {publisher_index} process did not exit ' |
| 372 | + 'gracefully; it was forcefully terminated.', |
| 373 | + verbosity) |
| 374 | + |
339 | 375 | return |
340 | 376 |
|
341 | 377 |
|
|
0 commit comments