/* Test that OOM error suppression works. Copyright (C) 2025 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ /* This test reacts to the reject_oom and inject_error environment variables. It is never executed automatically because it can run for a very long time on large systems, and is generally stressful to the system. */ #include #include #include #include #include #include #include #include /* If true, support_accept_oom is called. */ static bool accept_oom; /* System page size. Allocations are always at least that large. */ static size_t page_size; /* All allocated bytes. */ static size_t total_bytes; /* Try to allocate SIZE bytes of memory, and ensure that is backed by actual memory. */ static bool populate_memory (size_t size) { TEST_COMPARE (size % page_size, 0); char *ptr = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (ptr == MAP_FAILED) return false; if (accept_oom) support_accept_oom (true); /* Ensure that the kernel allocates backing storage. Make the pages distinct using the total_bytes counter. */ for (size_t offset = 0; offset < size; offset += page_size) { memcpy (ptr + offset, &total_bytes, sizeof (total_bytes)); total_bytes += page_size; } if (accept_oom) support_accept_oom (false); return true; } static int do_test (void) { if (getenv ("oom_test_active") == NULL) { puts ("info: This test does nothing by default."); puts ("info: Set the oom_test_active environment variable to enable it."); puts ("info: Consider testing with inject_error and reject_oom as well."); return 0; } accept_oom = getenv ("reject_oom") == NULL; page_size = sysconf (_SC_PAGESIZE); size_t size = page_size; /* The environment variable can be set to trigger a test failure. The OOM event should not obscure this error. */ TEST_COMPARE_STRING (getenv ("inject_error"), NULL); /* Grow the allocation until allocation fails. */ while (true) { size_t new_size = 2 * size; if (new_size == 0 || !populate_memory (new_size)) break; size = new_size; } while (true) { if (!populate_memory (size)) { /* Decrease size and see if the allocation succeeds. */ size /= 2; if (size < page_size) FAIL_UNSUPPORTED ("could not trigger OOM" " after allocating %zu bytes", total_bytes); } } return 0; } #include