| 184 | } |
| 185 | |
| 186 | void test_wait_multi_children(void* /*arg*/) { |
| 187 | klog::Info("=== Wait Multi Children Test ==="); |
| 188 | bool passed = true; |
| 189 | |
| 190 | auto& tm = TaskManagerSingleton::instance(); |
| 191 | auto* self = tm.GetCurrentTask(); |
| 192 | |
| 193 | constexpr int kChildCount = 3; |
| 194 | int exit_codes[kChildCount] = {10, 20, 30}; |
| 195 | |
| 196 | for (int i = 0; i < kChildCount; ++i) { |
| 197 | auto child = kstd::make_unique<TaskControlBlock>( |
| 198 | "MultiChild", 10, multi_child_work, |
| 199 | reinterpret_cast<void*>(static_cast<uintptr_t>(exit_codes[i]))); |
| 200 | child->aux->parent_pid = self->pid; |
| 201 | auto* raw = child.get(); |
| 202 | tm.AddTask(std::move(child)); |
| 203 | klog::Info("test_wait_multi_children: spawned child {} pid={}", i, |
| 204 | raw->pid); |
| 205 | } |
| 206 | |
| 207 | // Collect all children via Wait(-1, ..., nohang=true, ...) |
| 208 | int collected = 0; |
| 209 | int retries = 400; // 400 * 50ms = 20s timeout |
| 210 | |
| 211 | while (collected < kChildCount && retries > 0) { |
| 212 | int status = 0; |
| 213 | auto result = tm.Wait(static_cast<Pid>(-1), &status, true, false); |
| 214 | |
| 215 | if (result.has_value() && result.value() > 0) { |
| 216 | klog::Info("test_wait_multi_children: reaped pid={} status={}", |
| 217 | result.value(), status); |
| 218 | collected++; |
| 219 | } else { |
| 220 | (void)sys_sleep(50); |
| 221 | retries--; |
| 222 | } |
| 223 | } |
| 224 | |
| 225 | if (collected != kChildCount) { |
| 226 | klog::Err("test_wait_multi_children: collected {} of {} children", |
| 227 | collected, kChildCount); |
| 228 | passed = false; |
| 229 | } |
| 230 | |
| 231 | if (!passed) { |
| 232 | g_tests_failed++; |
| 233 | } |
| 234 | g_tests_completed++; |
| 235 | klog::Info("Wait Multi Children Test: {}", passed ? "PASSED" : "FAILED"); |
| 236 | sys_exit(passed ? 0 : 1); |
| 237 | } |
| 238 | |
| 239 | } // namespace |
| 240 | |