Skip to content

Commit

Permalink
[webkitcorepy] Create process-like Thread object
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=245913
<rdar://100642035>

Reviewed by Dewei Zhu and David Kilzer.

* Tools/Scripts/libraries/webkitcorepy/setup.py: Bump version.
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Ditto.
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Import Thread object
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/subprocess_utils.py:
(Thread):
(Thread.terminated): Check if the current thread has it's termination flag flipped.
(Thread.__init__):
(Thread.poll): Check if the Thread is running.
(Thread.terminate): Set terminate flag.
(Thread.kill): Ditto.
(Thread.__enter__): Start thread.
(Thread.__exit__): Join thread.
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/tests/subprocess_utils_unittest.py:
(SubprocessUtils.test_thread):
(SubprocessUtils.test_killed_thread):

Canonical link: https://commits.webkit.org/255370@main
  • Loading branch information
JonWBedard committed Oct 10, 2022
1 parent b847983 commit dc2cb0f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Tools/Scripts/libraries/webkitcorepy/setup.py
Expand Up @@ -30,7 +30,7 @@ def readme():

setup(
name='webkitcorepy',
version='0.13.16',
version='0.13.17',
description='Library containing various Python support classes and functions.',
long_description=readme(),
classifiers=[
Expand Down
4 changes: 2 additions & 2 deletions Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py
Expand Up @@ -32,7 +32,7 @@
from webkitcorepy.version import Version
from webkitcorepy.string_utils import BytesIO, StringIO, UnicodeIO, unicode
from webkitcorepy.timeout import Timeout
from webkitcorepy.subprocess_utils import TimeoutExpired, CompletedProcess, run
from webkitcorepy.subprocess_utils import TimeoutExpired, CompletedProcess, run, Thread
from webkitcorepy.output_capture import LoggerCapture, OutputCapture, OutputDuplicate
from webkitcorepy.task_pool import TaskPool
from webkitcorepy.terminal import Terminal
Expand All @@ -44,7 +44,7 @@
from webkitcorepy.editor import Editor
from webkitcorepy.file_lock import FileLock

version = Version(0, 13, 16)
version = Version(0, 13, 17)

from webkitcorepy.autoinstall import Package, AutoInstall
if sys.version_info > (3, 0):
Expand Down
@@ -1,4 +1,4 @@
# Copyright (C) 2020 Apple Inc. All rights reserved.
# Copyright (C) 2020-2022 Apple Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
Expand All @@ -24,6 +24,7 @@
import subprocess
import sys
import time
import threading

from webkitcorepy import Timeout, string_utils

Expand Down Expand Up @@ -146,3 +147,32 @@ def decode(string):
if check and retcode:
raise subprocess.CalledProcessError(retcode, popenargs[0], output=decode(stdout), stderr=decode(stderr))
return CompletedProcess(popenargs[0], retcode, decode(stdout), decode(stderr))


class Thread(threading.Thread):
@classmethod
def terminated(cls):
return getattr(threading.current_thread(), '_terminated', False)

def __init__(self, *args, **kwargs):
super(Thread, self).__init__(*args, **kwargs)
self._terminated = False

def poll(self):
return None if self.is_alive() else {True: 1, False: 0}.get(self._terminated, -1)

def terminate(self):
self._terminated = True

def kill(self):
self._terminated = True

def __enter__(self):
self.start()
return self

def __exit__(self, *args, **kwargs):
with Timeout.DisableAlarm():
current_time = time.time()
Timeout.check(current_time=current_time)
self.join(Timeout.difference(current_time=current_time))
Expand Up @@ -21,9 +21,10 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import sys
import time
import unittest

from webkitcorepy import OutputCapture, run, TimeoutExpired, Timeout
from webkitcorepy import OutputCapture, run, TimeoutExpired, Timeout, Thread


class SubprocessUtils(unittest.TestCase):
Expand All @@ -40,6 +41,38 @@ def test_run_exit(self):
self.assertEqual(result.stdout, None)
self.assertEqual(result.stderr, None)

def test_thread(self):
data = dict()

def f():
data['finished'] = True

t = Thread(target=f)
with t:
pass

self.assertEqual(t.poll(), 0)
self.assertTrue(data.get('finished', False))

def test_killed_thread(self):
data = dict()

def f():
data['iteration'] = 0
for x in range(10):
if Thread.terminated():
break
data['iteration'] = x
time.sleep(.1)

t = Thread(target=f)
with t:
self.assertIsNone(t.poll())
t.kill()

self.assertEqual(t.poll(), 1)
self.assertNotEqual(data.get('iteration', 9), 9)

# Without signal.alarm, the timeout argument will not work in Python 2
if Timeout.SIGALRM or sys.version_info > (3, 0):
def test_run_timeout(self):
Expand Down

0 comments on commit dc2cb0f

Please sign in to comment.