Skip to content

Commit 200f221

Browse files
committed
session: implement forcibly stop
Change the way we complete session by introducing forcibly stop. The way that kirk works after this patch is the following: - if user sends SIGINT or CTRL+C, we simply wait for the running tests to complete and finally stop the session - if user sends SIGINT or CTRL+C again, we stop any execution on the SUT and we terminate the testing suite, flagging the killed test as TSKIP Signed-off-by: Andrea Cervesato <andrea.cervesato@suse.com> Closes: #78
1 parent 6cdb545 commit 200f221

File tree

4 files changed

+45
-21
lines changed

4 files changed

+45
-21
lines changed

libkirk/ltp.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import logging
1111
import os
1212
import re
13+
import signal
1314
from typing import (
1415
Any,
1516
Dict,
@@ -384,6 +385,8 @@ async def read_result(
384385
warnings = 1
385386
elif retcode == 32:
386387
skipped = 1
388+
elif retcode == -signal.SIGKILL:
389+
skipped = 1
387390
elif not error:
388391
failed = 1
389392

libkirk/main.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,21 @@ async def session_run() -> None:
446446
if monitor:
447447
await monitor.stop()
448448

449+
def _session_stop() -> None:
450+
"""
451+
Stop the session.
452+
"""
453+
loop.run_until_complete(
454+
# pyrefly: ignore[bad-argument-type]
455+
asyncio.gather(
456+
*[
457+
session.stop(),
458+
libkirk.events.stop(),
459+
]
460+
)
461+
)
462+
libkirk.cancel_tasks(loop)
463+
449464
loop = libkirk.get_event_loop()
450465
exit_code = RC_OK
451466

@@ -460,20 +475,9 @@ async def session_run() -> None:
460475
exit_code = RC_ERROR
461476
finally:
462477
try:
463-
# at this point loop has been closed, so we can collect all
464-
# tasks and cancel them
465-
loop.run_until_complete(
466-
# pyrefly: ignore[bad-argument-type]
467-
asyncio.gather(
468-
*[
469-
session.stop(),
470-
libkirk.events.stop(),
471-
]
472-
)
473-
)
474-
libkirk.cancel_tasks(loop)
478+
_session_stop()
475479
except KeyboardInterrupt:
476-
pass
480+
_session_stop()
477481

478482
parser.exit(exit_code)
479483

libkirk/session.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ def __init__(
9090
self._sut = sut
9191
self._exec_timeout = exec_timeout
9292
self._force_parallel = force_parallel
93-
self._stop = False
93+
self._stop_cnt = 0
94+
self._stop_lock = asyncio.Lock()
9495
self._exec_lock = asyncio.Lock()
9596
self._run_lock = asyncio.Lock()
9697
self._results = []
@@ -356,7 +357,7 @@ async def _exec_command(self, command: str) -> None:
356357
except asyncio.TimeoutError:
357358
exc = KirkException(f"Command timeout: {repr(command)}")
358359
except KirkException as err:
359-
if not self._stop:
360+
if self._stop_cnt == 0:
360361
exc = err
361362

362363
if exc:
@@ -366,16 +367,24 @@ async def _inner_stop(self) -> None:
366367
"""
367368
Stop scheduler and SUT.
368369
"""
370+
if self._stop_cnt > 1:
371+
# by stopping SUT first, we cause scheduler to complete
372+
# current test immediatelly without waiting
373+
await self._stop_sut()
374+
369375
if self._scheduler:
370376
await self._scheduler.stop()
371377

372-
await self._stop_sut()
378+
if self._stop_cnt < 1:
379+
await self._stop_sut()
373380

374381
async def stop(self) -> None:
375382
"""
376383
Stop the current session.
377384
"""
378-
self._stop = True
385+
async with self._stop_lock:
386+
self._stop_cnt += 1
387+
379388
try:
380389
await self._inner_stop()
381390

@@ -385,8 +394,12 @@ async def stop(self) -> None:
385394
async with self._exec_lock:
386395
pass
387396
finally:
388-
await libkirk.events.fire("session_stopped")
389-
self._stop = False
397+
if self._stop_cnt == 1:
398+
await libkirk.events.fire("session_stopped")
399+
elif self._stop_cnt > 1:
400+
await libkirk.events.fire("session_killed")
401+
402+
self._stop_cnt = 0
390403

391404
async def _schedule_once(self, suites_obj: List[Suite]) -> None:
392405
"""
@@ -403,7 +416,7 @@ async def _schedule_infinite(self, suites_obj: List[Suite]) -> None:
403416
suites_list.extend(suites_obj)
404417

405418
count = 1
406-
while not self._stop:
419+
while self._stop_cnt == 0:
407420
await self._schedule_once(suites_obj)
408421
if self._scheduler.stopped:
409422
break
@@ -516,7 +529,7 @@ async def run(
516529

517530
await self._run_scheduler(suites_obj, runtime)
518531
except KirkException as err:
519-
if not self._stop:
532+
if self._stop_cnt == 0:
520533
self._logger.exception(err)
521534
await libkirk.events.fire("session_error", str(err))
522535
raise err

libkirk/ui.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(self, no_colors: bool = False) -> None:
4646
libkirk.events.register("session_restore", self.session_restore)
4747
libkirk.events.register("session_started", self.session_started)
4848
libkirk.events.register("session_stopped", self.session_stopped)
49+
libkirk.events.register("session_killed", self.session_killed)
4950
libkirk.events.register("sut_start", self.sut_start)
5051
libkirk.events.register("sut_stop", self.sut_stop)
5152
libkirk.events.register("sut_restart", self.sut_restart)
@@ -128,6 +129,9 @@ async def session_started(self, tmpdir: str) -> None:
128129
async def session_stopped(self) -> None:
129130
await self._print("Session stopped")
130131

132+
async def session_killed(self) -> None:
133+
await self._print("Session killed")
134+
131135
async def sut_start(self, sut: str) -> None:
132136
await self._print(f"Connecting to SUT: {sut}")
133137

0 commit comments

Comments
 (0)