mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
edenapi: edenapi._spawnthread -> util.threaded
Summary: Move the wrapper to util.py. It'll be used in dispatch.py to make the entire command Ctrl+C friendly. Reviewed By: singhsrb Differential Revision: D23759715 fbshipit-source-id: fa2098362413dcfd0b68e05455aad543a6980907
This commit is contained in:
parent
c4e2f5cb0f
commit
51a9d37730
@ -5,11 +5,9 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import threading
|
||||
|
||||
from bindings import edenapi
|
||||
|
||||
from . import error
|
||||
from . import util
|
||||
from .i18n import _
|
||||
|
||||
|
||||
@ -27,46 +25,10 @@ class pyclient(object):
|
||||
def __getattr__(self, name):
|
||||
method = getattr(self._rustclient, name)
|
||||
method = _warnexceptions(self._ui)(method)
|
||||
method = _spawnthread(method)
|
||||
method = util.threaded(method)
|
||||
return method
|
||||
|
||||
|
||||
def _spawnthread(func):
|
||||
"""Decorator that spawns a new Python thread to run the wrapped function.
|
||||
|
||||
This is useful for FFI calls to allow the Python interpreter to handle
|
||||
signals during the FFI call. For example, without this it would not be
|
||||
possible to interrupt the process with Ctrl-C during a long-running FFI
|
||||
call.
|
||||
"""
|
||||
|
||||
def wrapped(*args, **kwargs):
|
||||
result = ["err", error.Abort(_("thread aborted unexpectedly"))]
|
||||
|
||||
def target(*args, **kwargs):
|
||||
try:
|
||||
result[:] = ["ok", func(*args, **kwargs)]
|
||||
except Exception as e:
|
||||
result[:] = ["err", e]
|
||||
|
||||
thread = threading.Thread(target=target, args=args, kwargs=kwargs)
|
||||
thread.start()
|
||||
|
||||
# XXX: Need to repeatedly poll the thread because blocking
|
||||
# indefinitely on join() would prevent the interpreter from
|
||||
# handling signals.
|
||||
while thread.is_alive():
|
||||
thread.join(1)
|
||||
|
||||
variant, value = result
|
||||
if variant == "err":
|
||||
raise value
|
||||
|
||||
return value
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def _warnexceptions(ui):
|
||||
"""Decorator that catches certain exceptions defined by the Rust bindings
|
||||
and emits a user-friendly message before re-raising the exception.
|
||||
|
@ -47,6 +47,7 @@ import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import threading
|
||||
import time
|
||||
import traceback
|
||||
import types
|
||||
@ -4300,6 +4301,42 @@ class traced(object):
|
||||
tracer.exit(self.spanid)
|
||||
|
||||
|
||||
def threaded(func):
|
||||
"""Decorator that spawns a new Python thread to run the wrapped function.
|
||||
|
||||
This is useful for FFI calls to allow the Python interpreter to handle
|
||||
signals during the FFI call. For example, without this it would not be
|
||||
possible to interrupt the process with Ctrl-C during a long-running FFI
|
||||
call.
|
||||
"""
|
||||
|
||||
def wrapped(*args, **kwargs):
|
||||
result = ["err", error.Abort(_("thread aborted unexpectedly"))]
|
||||
|
||||
def target(*args, **kwargs):
|
||||
try:
|
||||
result[:] = ["ok", func(*args, **kwargs)]
|
||||
except Exception as e:
|
||||
result[:] = ["err", e]
|
||||
|
||||
thread = threading.Thread(target=target, args=args, kwargs=kwargs)
|
||||
thread.start()
|
||||
|
||||
# XXX: Need to repeatedly poll the thread because blocking
|
||||
# indefinitely on join() would prevent the interpreter from
|
||||
# handling signals.
|
||||
while thread.is_alive():
|
||||
thread.join(1)
|
||||
|
||||
variant, value = result
|
||||
if variant == "err":
|
||||
raise value
|
||||
|
||||
return value
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def info(name, **kwargs):
|
||||
"""Log a instant event in tracing data"""
|
||||
tracer.event(
|
||||
|
Loading…
Reference in New Issue
Block a user