|
2 | 2 | #include <catch2/matchers/catch_matchers_string.hpp> |
3 | 3 |
|
4 | 4 | #include <tinykvm/machine.hpp> |
| 5 | +#include <linux/kvm.h> |
5 | 6 | extern std::vector<uint8_t> build_and_load(const std::string& code); |
6 | 7 | static const uint64_t MAX_MEMORY = 8ul << 20; /* 8MB */ |
7 | | -static const uint64_t MAX_COWMEM = 3ul << 20; /* 1MB */ |
| 8 | +static const uint64_t MAX_COWMEM = 3ul << 20; /* 3MB */ |
8 | 9 | static const std::vector<std::string> env { |
9 | 10 | "LC_TYPE=C", "LC_ALL=C", "USER=root" |
10 | 11 | }; |
@@ -566,3 +567,74 @@ int func2() { |
566 | 567 | REQUIRE(fork2.return_value() == 22222); |
567 | 568 | } |
568 | 569 | } |
| 570 | + |
| 571 | +TEST_CASE("Fork before main()", "[Fork]") |
| 572 | +{ |
| 573 | + const auto binary = build_and_load(R"M( |
| 574 | +#include <stdio.h> |
| 575 | +extern void _exit(int); |
| 576 | +int main() { |
| 577 | + printf("Hello World!\n"); |
| 578 | + _exit(666); |
| 579 | + return 666; |
| 580 | +} |
| 581 | +static unsigned value = 12345; |
| 582 | +void set_value(int v) { |
| 583 | + value = v; |
| 584 | +} |
| 585 | +int func1() { |
| 586 | + return value; |
| 587 | +} |
| 588 | +int func2() { |
| 589 | + return 54321; |
| 590 | +} |
| 591 | +)M"); |
| 592 | + |
| 593 | + tinykvm::Machine machine1 { binary, { |
| 594 | + .max_mem = 10ull << 20, // We need 10mb because of fragmentation |
| 595 | + } }; |
| 596 | + machine1.setup_linux({"fork"}, env); |
| 597 | + machine1.prepare_copy_on_write(); |
| 598 | + REQUIRE(machine1.is_forkable()); |
| 599 | + REQUIRE(!machine1.is_forked()); |
| 600 | + |
| 601 | + tinykvm::Machine machine2 { binary, { |
| 602 | + .max_mem = 10ull << 20, |
| 603 | + } }; |
| 604 | + machine2.prepare_copy_on_write(); // No Linux setup |
| 605 | + REQUIRE(machine2.is_forkable()); |
| 606 | + REQUIRE(!machine2.is_forked()); |
| 607 | + |
| 608 | + auto fork1 = tinykvm::Machine { machine1, { |
| 609 | + .max_cow_mem = MAX_COWMEM, |
| 610 | + .split_hugepages = true |
| 611 | + } }; |
| 612 | + |
| 613 | + for (int i = 0; i < 100; i++) |
| 614 | + { |
| 615 | + fork1.run(4.0f); |
| 616 | + REQUIRE(fork1.return_value() == 666); |
| 617 | + |
| 618 | + fork1.reset_to(machine1, { |
| 619 | + .max_cow_mem = 4ul << 20, |
| 620 | + .split_hugepages = true |
| 621 | + }); |
| 622 | + } |
| 623 | + |
| 624 | + auto fork2 = tinykvm::Machine { machine2, { |
| 625 | + .max_cow_mem = MAX_COWMEM, |
| 626 | + .split_hugepages = true |
| 627 | + } }; |
| 628 | + |
| 629 | + for (int i = 0; i < 100; i++) |
| 630 | + { |
| 631 | + fork2.setup_linux({"fork"}, env); |
| 632 | + fork2.run(4.0f); |
| 633 | + REQUIRE(fork2.return_value() == 666); |
| 634 | + |
| 635 | + fork2.reset_to(machine2, { |
| 636 | + .max_cow_mem = 4ul << 20, |
| 637 | + .split_hugepages = true |
| 638 | + }); |
| 639 | + } |
| 640 | +} |
0 commit comments