diff --git a/script/src/verify/tests/ckb_latest/features_since_v2023.rs b/script/src/verify/tests/ckb_latest/features_since_v2023.rs index d6539cfcb1..a465c6515a 100644 --- a/script/src/verify/tests/ckb_latest/features_since_v2023.rs +++ b/script/src/verify/tests/ckb_latest/features_since_v2023.rs @@ -1320,3 +1320,9 @@ fn check_spawn_io_cycles() { assert_eq!(cycles2 - cycles1, offset_size / 2); } + +#[test] +fn check_spawn_saturate_memory() { + let result = simple_spawn_test("testdata/spawn_saturate_memory", &[0]); + assert_eq!(result.is_ok(), SCRIPT_VERSION == ScriptVersion::V2); +} diff --git a/script/testdata/Makefile b/script/testdata/Makefile index 71325a06c4..8d72cc3900 100644 --- a/script/testdata/Makefile +++ b/script/testdata/Makefile @@ -74,7 +74,8 @@ ALL_BINS := jalr_zero \ spawn_fuzzing \ spawn_huge_swap \ spawn_cycles \ - spawn_io_cycles + spawn_io_cycles \ + spawn_saturate_memory ALL_LIBS := is_even.lib \ add1.lib sub1.lib mul2.lib div2.lib @@ -162,3 +163,4 @@ spawn_fuzzing: spawn_fuzzing.c spawn_utils.h spawn_huge_swap: spawn_huge_swap.c spawn_utils.h spawn_cycles: spawn_cycles.c spawn_utils.h spawn_io_cycles: spawn_io_cycles.c spawn_utils.h +spawn_saturate_memory: spawn_saturate_memory.c spawn_utils.h diff --git a/script/testdata/spawn_saturate_memory b/script/testdata/spawn_saturate_memory new file mode 100755 index 0000000000..08e51f96c8 Binary files /dev/null and b/script/testdata/spawn_saturate_memory differ diff --git a/script/testdata/spawn_saturate_memory.c b/script/testdata/spawn_saturate_memory.c new file mode 100644 index 0000000000..de977b10db --- /dev/null +++ b/script/testdata/spawn_saturate_memory.c @@ -0,0 +1,45 @@ +#include "spawn_utils.h" + +#define MAX_MEMORY (4 * 1024 * 1024) +#define PAGE_SIZE (4 * 1024) + +extern char _end[]; + +void dirty_all_pages() { + uint64_t addr = (uint64_t)_end; + while (addr < MAX_MEMORY) { + uint8_t* ptr = (uint8_t*)addr; + *ptr = 0; + addr += PAGE_SIZE; + } +} + +int main(int argc, const char* argv[]) { + int err = 0; + if (argc > 0) { + // child + dirty_all_pages(); + uint64_t inherited_fds[2]; + size_t inherited_fds_length = 2; + err = ckb_inherited_file_descriptors(inherited_fds, &inherited_fds_length); + uint64_t length = MAX_MEMORY; + // Write a piece of data starting from address 0 with a size of 4M. + // It should not consume any memory. + err = ckb_write(inherited_fds[CKB_STDOUT], 0, &length); + // should be blocked forever since there is no reading on other end + CHECK(err); + } else { + // parent + for (size_t i = 0; i < 15; i++) { + uint64_t pid = 0; + const char* argv[] = {"", 0}; + uint64_t fds[2] = {0}; + err = full_spawn(0, 1, argv, fds, &pid); + CHECK(err); + } + dirty_all_pages(); + } + +exit: + return err; +}