Skip to content

Commit

Permalink
Use sio2jail on WSL (#265)
Browse files Browse the repository at this point in the history
* Use sio2jail on WSL

WSL2 (released 2019) is based on a Linux VM. In general its behavior is
consistent with any other Linux system running in a VM, so there should
be no reason to discriminate WSL under `util.is_linux()`.

In the future, we might want to check for specific features such as
perf counters being supported, but that is an orthogonal concern.

I have tested with several people using WSL across relatively modern
laptops (Intel 8th gen and up) and in all cases the Intel PMU driver
passed through enough perf counters for sio2jail to work.

If we wanted to test support for sio2jail more thoroughly, I suspect the
best method might be to actually try running sio2jail or the perf tool.

* Improve diagnostic for sio2jail check failure

* Avoid nested quotes in f-string
  • Loading branch information
j4b6ski authored Dec 8, 2024
1 parent ed788f8 commit 5bebd72
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/sinol_make/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def configure_parsers():


def check_sio2jail():
if util.is_linux() and not sio2jail.check_sio2jail():
if sio2jail.sio2jail_supported() and not sio2jail.check_sio2jail():
print(util.warning('Up to date `sio2jail` in `~/.local/bin/` not found, installing new version...'))
try:
if sio2jail.install_sio2jail():
Expand Down
8 changes: 4 additions & 4 deletions src/sinol_make/commands/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def configure_subparser(self, subparser):
After running the solutions, it compares the solutions\' scores with the ones saved in config.yml.'
)

default_timetool = 'sio2jail' if util.is_linux() else 'time'
default_timetool = 'sio2jail' if sio2jail.sio2jail_supported() else 'time'

parser.add_argument('-s', '--solutions', type=str, nargs='+',
help='solutions to be run, for example prog/abc{b,s}*.{cpp,py}')
Expand Down Expand Up @@ -764,7 +764,7 @@ def validate_arguments(self, args):

def use_sio2jail():
timetool_path = None
if not util.is_linux():
if not sio2jail.sio2jail_supported():
util.exit_with_error('As `sio2jail` works only on Linux-based operating systems,\n'
'we do not recommend using operating systems such as macOS.\n'
'Nevertheless, you can still run sinol-make by specifying\n'
Expand All @@ -789,12 +789,12 @@ def use_time():

timetool_path, timetool_name = None, None
preferred_timetool = self.contest.preferred_timetool()
if preferred_timetool == 'sio2jail' and util.is_linux():
if preferred_timetool == 'sio2jail' and sio2jail.sio2jail_supported():
use_default_timetool = use_sio2jail
elif preferred_timetool == 'time':
use_default_timetool = use_time
else:
use_default_timetool = use_sio2jail if util.is_linux() else use_time
use_default_timetool = use_sio2jail if sio2jail.sio2jail_supported() else use_time

if args.time_tool is None and self.config.get('sinol_undocumented_time_tool', '') != '':
if self.config.get('sinol_undocumented_time_tool', '') == 'sio2jail':
Expand Down
32 changes: 23 additions & 9 deletions src/sinol_make/sio2jail/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,14 @@ def install_sio2jail(directory=None):

def check_perf_counters_enabled():
"""
Checks if `kernel.perf_event_paranoid` is set to -1.
:return:
Checks if sio2jail is able to use perf counters to count instructions.
"""
if not util.is_linux() or not check_sio2jail():
if not sio2jail_supported() or not check_sio2jail():
return

with open('/proc/sys/kernel/perf_event_paranoid') as f:
perf_event_paranoid = int(f.read())

sio2jail = get_default_sio2jail_path()
test_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'perf_test.py')
python_executable = sys.executable
Expand All @@ -94,9 +96,21 @@ def check_perf_counters_enabled():
process.terminate()

if output != "Test string\n":
util.exit_with_error("To use the recommended tool for measuring time called `sio2jail`, please:\n"
"- execute `sudo sysctl kernel.perf_event_paranoid=-1` to make `sio2jail` work for\n"
" the current system session,\n"
"- or add `kernel.perf_event_paranoid=-1` to `/etc/sysctl.conf`\n"
" and reboot to permanently make sio2jail work.\n"
"For more details, see https://github.com/sio2project/sio2jail#running.\n")
max_perf_event_paranoid = 2
if perf_event_paranoid > max_perf_event_paranoid:
hint = (f"You have `kernel.perf_event_paranoid` set to `{perf_event_paranoid}`"
", which might be preventing userspace perf counters from working.\n"
f"Try running: `sudo sysctl kernel.perf_event_paranoid={max_perf_event_paranoid}`\n"
"If that fixes the problem, you can set this permanently by adding "
f"`kernel.perf_event_paranoid={max_perf_event_paranoid}` to `/etc/sysctl.conf` and rebooting.\n")
else:
hint = ("Your kernel, drivers, or hardware might be too old.\n"
"Check if the Intel PMU driver is loaded: `dmesg | grep -i 'perf'`\n"
"You can also check if the perf tool works correctly: `perf stat -e instructions:u -- sleep 0`\n"
"(if perf can't be found, it might be located in: `/usr/lib/linux-tools/*/perf`).\n")
cmdline = " ".join(process.args)
util.exit_with_error(f"Failed performance counters test: `{cmdline}`\n"
+ hint +
"Alternatively, you can run sinol-make without instruction counting"
", by adding the `--time-tool time` flag.\n"
"For more details, see https://github.com/sio2project/sio2jail#running.\n")
4 changes: 2 additions & 2 deletions src/sinol_make/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ def is_wsl():

def is_linux():
"""
Function to check if the program is running on Linux and not WSL.
Function to check if the program is running on Linux (including WSL).
"""
return sys.platform == "linux" and not is_wsl()
return sys.platform == "linux"


def is_macos():
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import fnmatch
import multiprocessing as mp

from sinol_make import util
from sinol_make import sio2jail, util
from sinol_make.helpers import compile, paths, cache, oicompare
from sinol_make.interfaces.Errors import CompilationError

Expand Down Expand Up @@ -99,7 +99,7 @@ def pytest_generate_tests(metafunc):
time_tools = []
if metafunc.config.getoption("time_tool") != []:
time_tools = metafunc.config.getoption("time_tool")
elif util.is_linux():
elif sio2jail.sio2jail_supported():
time_tools = ["sio2jail", "time"]
else:
time_tools = ["time"]
Expand All @@ -118,6 +118,6 @@ def pytest_collection_modifyitems(config, items: List[pytest.Item]):

for item in items:
if "sio2jail" in item.keywords:
if not util.is_linux() or config.getoption("--time-tool") == ["time"] or \
if not sio2jail.sio2jail_supported() or config.getoption("--time-tool") == ["time"] or \
config.getoption("--github-runner"):
item.add_marker(pytest.mark.skip(reason="sio2jail required"))
10 changes: 5 additions & 5 deletions tests/test_sio2jail.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

@pytest.mark.github_runner
def test_install_sio2jail():
if sys.platform != 'linux':
if not sio2jail.sio2jail_supported():
return

try:
Expand All @@ -34,7 +34,7 @@ def test_install_sio2jail():

@pytest.mark.github_runner
def test_check_sio2jail():
if sys.platform != 'linux':
if not sio2jail.sio2jail_supported():
return

try:
Expand All @@ -59,7 +59,7 @@ def test_perf_counters_not_set():
"""
Test `sio2jail.check_perf_counters_enabled` with perf counters disabled
"""
if sys.platform != 'linux':
if not sio2jail.sio2jail_supported():
return

sio2jail.install_sio2jail()
Expand All @@ -72,7 +72,7 @@ def test_perf_counters_set():
"""
Test `sio2jail.check_perf_counters_enabled` with perf counters enabled
"""
if not util.is_linux():
if not sio2jail.sio2jail_supported():
return
sio2jail.check_perf_counters_enabled()

Expand All @@ -82,7 +82,7 @@ def test_updating():
"""
Test updating sio2jail
"""
if sys.platform != 'linux':
if not sio2jail.sio2jail_supported():
return
try:
os.remove(os.path.expanduser('~/.local/bin/oiejq'))
Expand Down

0 comments on commit 5bebd72

Please sign in to comment.