[PATCH v2 1/2] shell: add optional OOM protection
Andrea Cervesato <[email protected]> Thu, 30 Jul 2026 15:05:23 +0200
| Newsgroups | gmane.linux.ltp |
|---|---|
| Message-ID | <[email protected]> |
From: Andrea Cervesato <andrea.cervesato-IBi9RG/[email protected]> Add TST_OOM_PROTECTION to activate OOM protection in shell tests. When enabled, the shell harness shields itself from the OOM killer and runs the test in a child process, so it survives memory pressure and can still report results (e.g. during memcg stress tests). Signed-off-by: Andrea Cervesato <andrea.cervesato-IBi9RG/[email protected]> --- doc/developers/writing_tests.rst | 3 ++ testcases/lib/tests/shell_oom_protection.sh | 42 +++++++++++++++++++++ testcases/lib/tst_test.sh | 57 ++++++++++++++++++++++++++++- 3 files changed, 101 insertions(+), 1 deletion(-) diff --git a/doc/developers/writing_tests.rst b/doc/developers/writing_tests.rst index 4db57898fcf08b83e68be996f666e91c418838fc..2d5bc294083fa2b89212714f0a6c5e5c3f22777a 100644 --- a/doc/developers/writing_tests.rst +++ b/doc/developers/writing_tests.rst @@ -549,6 +549,9 @@ LTP C And Shell Test API Comparison * - not applicable - TST_FS_TYPE + * - not applicable + - TST_OOM_PROTECTION + .. list-table:: :header-rows: 1 diff --git a/testcases/lib/tests/shell_oom_protection.sh b/testcases/lib/tests/shell_oom_protection.sh new file mode 100755 index 0000000000000000000000000000000000000000..aeab36816ee7d8eeae9366d2199a0aabde73e25a --- /dev/null +++ b/testcases/lib/tests/shell_oom_protection.sh @@ -0,0 +1,42 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2026 Linux Test Project +# +# doc +# Verify that TST_OOM_PROTECTION shields the shell harness from the OOM +# killer and resets the test process oom_score_adj to 0. +# +# --- +# env +# { +# } +# --- + +TST_TESTFUNC=do_test +TST_OOM_PROTECTION=1 + +read_oom_score_adj() { + cat "/proc/$1/oom_score_adj" 2>/dev/null +} + +do_test() { + local self_score harness_score + + self_score=$(read_oom_score_adj self) + harness_score=$(read_oom_score_adj "$$") + + if [ "$self_score" = 0 ]; then + tst_res TPASS "test process has oom_score_adj reset to 0" + else + tst_res TFAIL "test process oom_score_adj is $self_score, expected 0" + fi + + if [ "$harness_score" = -1000 ]; then + tst_res TPASS "shell harness is protected from OOM" + else + tst_res TCONF "shell harness OOM protection unavailable" + fi +} + +. tst_test.sh +tst_run diff --git a/testcases/lib/tst_test.sh b/testcases/lib/tst_test.sh index 8701bb3903889b009f88ba98bac47534608cdd0a..48dacb432b953295ae4ad710e4f27ed87ac0a7e5 100644 --- a/testcases/lib/tst_test.sh +++ b/testcases/lib/tst_test.sh @@ -28,6 +28,57 @@ export TST_USR_GID="${LTP_USR_GID:-65534}" trap "tst_brk TBROK 'test interrupted'" INT trap "unset _tst_setup_timer_pid; tst_brk TBROK 'test terminated'" TERM +_tst_set_oom_score_adj() +{ + local value="$1" + local path="/proc/self/oom_score_adj" + + [ -e "$path" ] || return 0 + + echo "$value" > "$path" 2>/dev/null || return 0 +} + +_tst_enable_oom_protection() +{ + _tst_set_oom_score_adj -1000 +} + +_tst_disable_oom_protection() +{ + _tst_set_oom_score_adj 0 +} + +_tst_run_oom_protected() +{ + local _tst_pid + local _tst_ret + + # Shield the harness from the OOM killer and run the test in a child. + # The child keeps the default oom_score_adj so that it, and any process + # it spawns, stay killable under memory pressure while the harness + # survives to report results. + _tst_enable_oom_protection + + ( + _tst_disable_oom_protection + _TST_OOM_PROTECTION=0 + export _TST_OOM_PROTECTION + tst_run "$@" + ) & + _tst_pid=$! + + wait "$_tst_pid" + _tst_ret=$? + + if [ "$_tst_ret" -eq 137 ]; then + tst_res TINFO "Test was SIGKILLed: OOM killer or timeout?" + tst_res TINFO "On a slow machine try exporting LTP_TIMEOUT_MUL > 1" + tst_brk TBROK "Test killed!" + fi + + exit "$_tst_ret" +} + _tst_do_cleanup() { if [ -n "$TST_DO_CLEANUP" -a -n "$TST_CLEANUP" -a -z "$LTP_NO_CLEANUP" ]; then @@ -680,12 +731,16 @@ tst_run() local _tst_pattern='[='\''"} \t\/:`$\;|].*' local ret + if [ "$TST_OOM_PROTECTION" = 1 -a "$_TST_OOM_PROTECTION" != 0 ]; then + _tst_run_oom_protected "$@" + fi + if [ -n "$TST_TEST_PATH" ]; then for _tst_i in $(grep '^[^#]*\<TST_' "$TST_TEST_PATH" | sed "s/.*TST_//; s/$_tst_pattern//"); do case "$_tst_i" in ALL_FILESYSTEMS|DISABLE_APPARMOR|DISABLE_SELINUX);; SETUP|CLEANUP|TESTFUNC|ID|CNT|MIN_KVER);; - OPTS|USAGE|PARSE_ARGS|POS_ARGS);; + OPTS|USAGE|PARSE_ARGS|POS_ARGS|OOM_PROTECTION);; NEEDS_ROOT|NEEDS_TMPDIR|TMPDIR|NEEDS_DEVICE|DEVICE);; NEEDS_CMDS|NEEDS_MODULE|MODPATH|DATAROOT);; NEEDS_DRIVERS|FS_TYPE|MNTPOINT|MNT_PARAMS);; -- 2.51.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp