Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ repos:
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/asottile/yesqa
rev: v1.5.0
hooks:
- id: yesqa
- repo: https://github.com/asottile/pyupgrade
rev: v3.15.2
hooks:
Expand All @@ -16,10 +12,10 @@ repos:
rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.5.1
hooks:
- id: flake8
- id: ruff
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
Expand Down
17 changes: 17 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,21 @@ ignored-modules = ["pytest"]
[tool.pytest.ini_options]
log_level = "DEBUG"

[tool.ruff.lint]
select = [
# pycodestyle
"E",
# Pyflakes
"F",
# Flynt
"FLY",
# Perflint
"PERF",
# Ruff-specific rules
"RUF",
# pycodestyle
"W",
]
ignore = ["PERF203"]

[tool.setuptools_scm]
40 changes: 21 additions & 19 deletions src/ffpuppet/bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,27 @@
class Bootstrapper: # pylint: disable=missing-docstring
# see: searchfox.org/mozilla-central/source/netwerk/base/nsIOService.cpp
# include ports above 1023
BLOCKED_PORTS = {
1719,
1720,
1723,
2049,
3659,
4045,
5060,
5061,
6000,
6566,
6665,
6666,
6667,
6668,
6669,
6697,
10080,
}
BLOCKED_PORTS = frozenset(
(
1719,
1720,
1723,
2049,
3659,
4045,
5060,
5061,
6000,
6566,
6665,
6666,
6667,
6668,
6669,
6697,
10080,
)
)
# receive buffer size
BUF_SIZE = 4096
# duration of initial blocking socket operations
Expand Down
3 changes: 2 additions & 1 deletion src/ffpuppet/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,8 @@ def build_launch_cmd(
"-return-child-result",
"-batch",
"--args",
] + cmd
*cmd,
]

elif self._dbg in (Debugger.PERNOSCO, Debugger.RR):
rr_cmd = [
Expand Down
12 changes: 6 additions & 6 deletions src/ffpuppet/job_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@
class IOCounters(ctypes.Structure):
"""IOCounters"""

_fields_ = [
_fields_ = (
("read_operation_count", ctypes.c_ulonglong),
("write_operation_count", ctypes.c_ulonglong),
("other_operation_count", ctypes.c_ulonglong),
("read_transfer_count", ctypes.c_ulonglong),
("write_transfer_count", ctypes.c_ulonglong),
("other_transfer_count", ctypes.c_ulonglong),
]
)


class JobObjectBasicLimitInformation(ctypes.Structure):
"""JobObjectBasicLimitInformation"""

_fields_ = [
_fields_ = (
("per_process_user_time_limit", ctypes.wintypes.LARGE_INTEGER),
("per_job_user_time_limit", ctypes.wintypes.LARGE_INTEGER),
("limit_flags", ctypes.wintypes.DWORD),
Expand All @@ -47,20 +47,20 @@ class JobObjectBasicLimitInformation(ctypes.Structure):
("affinity", ctypes.wintypes.PULONG),
("priority_class", ctypes.wintypes.DWORD),
("scheduling_class", ctypes.wintypes.DWORD),
]
)


class JobObjectExtendedLimitInformation(ctypes.Structure):
"""JobObjectExtendedLimitInformation"""

_fields_ = [
_fields_ = (
("basic_limit_information", JobObjectBasicLimitInformation),
("io_info", IOCounters),
("process_memory_limit", ctypes.c_size_t),
("job_memory_limit", ctypes.c_size_t),
("peak_process_memory_used", ctypes.c_size_t),
("peak_job_memory_used", ctypes.c_size_t),
]
)


def config_job_object(handle: Handle, limit: int) -> None:
Expand Down
8 changes: 4 additions & 4 deletions src/ffpuppet/lsof.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def create_winerror(function: str) -> OSError: # pragma: no cover
class SystemHandleTableEntryInfoEx(ctypes.Structure):
"""NT API Handle table entry structure"""

_fields_ = [
_fields_ = (
("Object", ctypes.c_void_p),
("UniqueProcessId", ctypes.wintypes.HANDLE),
("HandleValue", ctypes.wintypes.HANDLE),
Expand All @@ -59,7 +59,7 @@ class SystemHandleTableEntryInfoEx(ctypes.Structure):
("ObjectTypeIndex", ctypes.c_ushort),
("HandleAttributes", ctypes.c_ulong),
("Reserved", ctypes.c_ulong),
]
)


def nt_query_system_handle_information_ex() -> ctypes.Structure:
Expand Down Expand Up @@ -93,11 +93,11 @@ def nt_query_system_handle_information_ex() -> ctypes.Structure:
class SystemHandleInformationEx(ctypes.Structure):
"""NT API Handle table structure"""

_fields_ = [
_fields_ = (
("NumberOfHandles", ctypes.c_void_p),
("Reserved", ctypes.c_void_p),
("Handles", SystemHandleTableEntryInfoEx * (num_handles or 0)),
]
)

return SystemHandleInformationEx.from_buffer(buf)

Expand Down
4 changes: 1 addition & 3 deletions src/ffpuppet/resources/testff.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,7 @@ def main() -> int: # pylint: disable=missing-docstring
if cmd == "memory":
sys.stdout.write("simulating high memory usage\n")
sys.stdout.flush()
blob = []
for _ in range(200):
blob.append("A" * 1024 * 1024)
_ = ["A" * 1024 * 1024 for _ in range(200)]
elif cmd == "soft_assert":
sys.stdout.write("simulating soft assertion\n")
sys.stdout.flush()
Expand Down
24 changes: 12 additions & 12 deletions src/ffpuppet/resources/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
from subprocess import Popen
from sys import executable
from time import perf_counter, sleep
from typing import Any, List
from typing import Any, Optional, Tuple

CHILD_PROCS: List["Popen[bytes]"] = []
LOG = getLogger(__name__)
SHUTDOWN = False
SOCKET_TIMEOUT = 60
Expand All @@ -29,6 +28,7 @@ def handle_signal(signum: int, _frame: Any) -> None:

def main(args: Namespace) -> int:
"""Mock a Firefox browser process tree for testing purposes"""
child_procs: Optional[Tuple["Popen[bytes]", ...]] = None
start = perf_counter()
try:
pid = getpid()
Expand All @@ -52,7 +52,7 @@ def main(args: Namespace) -> int:
assert not args.contentproc, f"-contentproc not expected! ({pid})"
LOG.info("Launcher process")
# pylint: disable=consider-using-with
CHILD_PROCS.append(Popen(cmd))
child_procs = (Popen(cmd),)
elif args.contentproc:
LOG.info("Content process (ppid: %r)", args.parent_pid)
with socket(AF_INET, SOCK_STREAM) as conn:
Expand All @@ -70,9 +70,8 @@ def main(args: Namespace) -> int:
cmd.append("--port")
cmd.append(str(srv.getsockname()[1]))
cmd.append("-contentproc")
for _ in range(args.procs):
# pylint: disable=consider-using-with
CHILD_PROCS.append(Popen(cmd))
# pylint: disable=consider-using-with
child_procs = tuple(Popen(cmd) for _ in range(args.procs))
# wait for processes to launch
for _ in range(args.procs):
conn, _ = srv.accept()
Expand All @@ -85,7 +84,7 @@ def main(args: Namespace) -> int:

# wait loop
while not SHUTDOWN and perf_counter() - start < args.duration:
if CHILD_PROCS and all(x.poll() is not None for x in CHILD_PROCS):
if child_procs and all(x.poll() is not None for x in child_procs):
break
sleep(0.1)

Expand All @@ -95,11 +94,12 @@ def main(args: Namespace) -> int:
finally:
if not args.contentproc:
args.sync.unlink(missing_ok=True)
for proc in CHILD_PROCS:
if proc.poll() is None:
proc.terminate()
for proc in CHILD_PROCS:
proc.wait(timeout=10)
if child_procs:
for proc in child_procs:
if proc.poll() is None:
proc.terminate()
for proc in child_procs:
proc.wait(timeout=10)
LOG.info("Exiting, runtime %0.3fs", perf_counter() - start)

return 0
Expand Down
4 changes: 1 addition & 3 deletions src/ffpuppet/test_ffpuppet.py
Original file line number Diff line number Diff line change
Expand Up @@ -491,12 +491,10 @@ def test_ffpuppet_20(tmp_path):

def test_ffpuppet_21(tmp_path):
"""test collecting and cleaning up ASan logs"""
test_logs = []
with FFPuppet() as ffp:
ffp.launch(TESTFF_BIN)
assert ffp._logs.path is not None
for i in range(4):
test_logs.append(Path(f"{ffp._logs.path / ffp._logs.PREFIX_SAN}.{i}"))
test_logs = [ffp._logs.path / f"{ffp._logs.PREFIX_SAN}.{i}" for i in range(4)]
# ignore benign ASan warning
with test_logs[0].open("w") as log_fp:
log_fp.write("==123==WARNING: Symbolizer buffer too small")
Expand Down
2 changes: 1 addition & 1 deletion src/ffpuppet/test_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def parse(opt_str):
llvm_sym_b.touch()
env = {
"ASAN_SYMBOLIZER_PATH": str(llvm_sym_a),
"ASAN_OPTIONS": f"external_symbolizer_path='{str(llvm_sym_b)}'",
"ASAN_OPTIONS": f"external_symbolizer_path='{llvm_sym_b}'",
}
env = _configure_sanitizers(env, tmp_path, "blah")
asan_opts = parse(env["ASAN_OPTIONS"])
Expand Down
4 changes: 2 additions & 2 deletions src/ffpuppet/test_sanitizer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_sanitizer_options_01(init, add, result, overwrite):
assert opt in result
# test __iter__
for opt, value in opts:
assert "=".join((opt, value)) in result
assert f"{opt}={value}" in result
# test __contains___
for opt in result:
assert opt.split("=")[0] in opts
Expand All @@ -76,7 +76,7 @@ def test_sanitizer_options_03(tmp_path):
# test exists
file = tmp_path / "file.bin"
file.touch()
opts.add("file", f"'{str(file)}'")
opts.add("file", f"'{file}'")
assert opts.check_path("file")
# test missing file
file.unlink()
Expand Down