Skip to content

Commit abe0be4

Browse files
committed
script: Add interrupt() and terminate()
Wire up the new frida-core Script.interrupt() and terminate() methods: - interrupt() aborts any JavaScript currently executing, leaving the script loaded and able to run again. - terminate() interrupts execution and unloads the script, so one stuck in a long-running or infinite operation can still be torn down.
1 parent a3c832b commit abe0be4

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

‎frida/_frida/__init__.pyi‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,12 @@ class Script(Object):
627627
"""
628628
...
629629

630+
def interrupt(self) -> None:
631+
"""
632+
Interrupt any JavaScript currently executing in the script.
633+
"""
634+
...
635+
630636
def post(self, message: str, data: Optional[Union[str, bytes]] = None) -> None:
631637
"""
632638
Post a JSON-encoded message to the script.
@@ -639,6 +645,12 @@ class Script(Object):
639645
"""
640646
...
641647

648+
def terminate(self) -> None:
649+
"""
650+
Interrupt execution and unload the script.
651+
"""
652+
...
653+
642654
def enable_debugger(self, port: Optional[int]) -> None:
643655
"""
644656
Enable the Node.js compatible script debugger

‎frida/_frida/extension.c‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,9 @@ static FridaPortalOptions * PySession_parse_portal_options (const gchar * certif
492492
static PyObject * PyScript_new_take_handle (FridaScript * handle);
493493
static PyObject * PyScript_is_destroyed (PyScript * self);
494494
static PyObject * PyScript_load (PyScript * self);
495+
static PyObject * PyScript_interrupt (PyScript * self);
495496
static PyObject * PyScript_unload (PyScript * self);
497+
static PyObject * PyScript_terminate (PyScript * self);
496498
static PyObject * PyScript_eternalize (PyScript * self);
497499
static PyObject * PyScript_post (PyScript * self, PyObject * args, PyObject * kw);
498500
static PyObject * PyScript_enable_debugger (PyScript * self, PyObject * args, PyObject * kw);
@@ -740,7 +742,9 @@ static PyMethodDef PyScript_methods[] =
740742
{
741743
{ "is_destroyed", (PyCFunction) PyScript_is_destroyed, METH_NOARGS, "Query whether the script has been destroyed." },
742744
{ "load", (PyCFunction) PyScript_load, METH_NOARGS, "Load the script." },
745+
{ "interrupt", (PyCFunction) PyScript_interrupt, METH_NOARGS, "Interrupt any JavaScript currently executing in the script." },
743746
{ "unload", (PyCFunction) PyScript_unload, METH_NOARGS, "Unload the script." },
747+
{ "terminate", (PyCFunction) PyScript_terminate, METH_NOARGS, "Interrupt execution and unload the script." },
744748
{ "eternalize", (PyCFunction) PyScript_eternalize, METH_NOARGS, "Eternalize the script." },
745749
{ "post", (PyCFunction) PyScript_post, METH_VARARGS | METH_KEYWORDS, "Post a JSON-encoded message to the script." },
746750
{ "enable_debugger", (PyCFunction) PyScript_enable_debugger, METH_VARARGS | METH_KEYWORDS, "Enable the Node.js compatible script debugger." },
@@ -4412,6 +4416,20 @@ PyScript_load (PyScript * self)
44124416
PyFrida_RETURN_NONE;
44134417
}
44144418

4419+
static PyObject *
4420+
PyScript_interrupt (PyScript * self)
4421+
{
4422+
GError * error = NULL;
4423+
4424+
Py_BEGIN_ALLOW_THREADS
4425+
frida_script_interrupt_sync (PY_GOBJECT_HANDLE (self), g_cancellable_get_current (), &error);
4426+
Py_END_ALLOW_THREADS
4427+
if (error != NULL)
4428+
return PyFrida_raise (error);
4429+
4430+
PyFrida_RETURN_NONE;
4431+
}
4432+
44154433
static PyObject *
44164434
PyScript_unload (PyScript * self)
44174435
{
@@ -4426,6 +4444,20 @@ PyScript_unload (PyScript * self)
44264444
PyFrida_RETURN_NONE;
44274445
}
44284446

4447+
static PyObject *
4448+
PyScript_terminate (PyScript * self)
4449+
{
4450+
GError * error = NULL;
4451+
4452+
Py_BEGIN_ALLOW_THREADS
4453+
frida_script_terminate_sync (PY_GOBJECT_HANDLE (self), g_cancellable_get_current (), &error);
4454+
Py_END_ALLOW_THREADS
4455+
if (error != NULL)
4456+
return PyFrida_raise (error);
4457+
4458+
PyFrida_RETURN_NONE;
4459+
}
4460+
44294461
static PyObject *
44304462
PyScript_eternalize (PyScript * self)
44314463
{

‎frida/core.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,15 @@ def load(self) -> None:
309309

310310
self._impl.load()
311311

312+
@cancellable
313+
def interrupt(self) -> None:
314+
"""
315+
Interrupt any JavaScript currently executing in the script, leaving it
316+
loaded and able to run again
317+
"""
318+
319+
self._impl.interrupt()
320+
312321
@cancellable
313322
def unload(self) -> None:
314323
"""
@@ -317,6 +326,15 @@ def unload(self) -> None:
317326

318327
self._impl.unload()
319328

329+
@cancellable
330+
def terminate(self) -> None:
331+
"""
332+
Interrupt execution and unload the script, even if it is stuck in a
333+
long-running or infinite operation
334+
"""
335+
336+
self._impl.terminate()
337+
320338
@cancellable
321339
def eternalize(self) -> None:
322340
"""

0 commit comments

Comments
 (0)