| 33 | } |
| 34 | |
| 35 | void test_fork_basic(void* /*arg*/) { |
| 36 | klog::Info("=== Fork Basic Test ==="); |
| 37 | bool passed = true; |
| 38 | |
| 39 | auto& tm = TaskManagerSingleton::instance(); |
| 40 | auto* self = tm.GetCurrentTask(); |
| 41 | Pid my_pid = self->pid; |
| 42 | |
| 43 | g_fork_child_pid = 0; |
| 44 | g_fork_child_tgid = 0; |
| 45 | g_fork_child_parent = 0; |
| 46 | |
| 47 | auto child = kstd::make_unique<TaskControlBlock>("ForkChild", 10, |
| 48 | fork_child_work, nullptr); |
| 49 | child->aux->parent_pid = my_pid; |
| 50 | auto* child_raw = child.get(); |
| 51 | tm.AddTask(std::move(child)); |
| 52 | Pid child_pid = child_raw->pid; |
| 53 | |
| 54 | int timeout = 100; |
| 55 | while (timeout-- > 0 && g_fork_child_pid.load() == 0) { |
| 56 | (void)sys_sleep(50); |
| 57 | } |
| 58 | |
| 59 | if (g_fork_child_pid.load() == 0) { |
| 60 | klog::Err("Fork child did not start"); |
| 61 | passed = false; |
| 62 | } |
| 63 | |
| 64 | if (passed) { |
| 65 | if (g_fork_child_pid.load() == my_pid) { |
| 66 | klog::Err("Child PID == parent PID"); |
| 67 | passed = false; |
| 68 | } |
| 69 | if (g_fork_child_tgid.load() != g_fork_child_pid.load()) { |
| 70 | klog::Err("Child tgid ({}) != child pid ({})", g_fork_child_tgid.load(), |
| 71 | g_fork_child_pid.load()); |
| 72 | passed = false; |
| 73 | } |
| 74 | if (g_fork_child_parent.load() != my_pid) { |
| 75 | klog::Err("Child parent_pid ({}) != my pid ({})", |
| 76 | g_fork_child_parent.load(), my_pid); |
| 77 | passed = false; |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | int status = 0; |
| 82 | auto wait_result = tm.Wait(child_pid, &status, false, false); |
| 83 | if (!wait_result.has_value() || wait_result.value() != child_pid) { |
| 84 | klog::Err("Wait for fork child failed"); |
| 85 | passed = false; |
| 86 | } else if (status != 42) { |
| 87 | klog::Err("Fork child exit code: {} (expected 42)", status); |
| 88 | passed = false; |
| 89 | } |
| 90 | |
| 91 | if (!passed) { |
| 92 | g_tests_failed++; |