|
1 | | -todo |
| 1 | +--- |
| 2 | +title: Hook Overview |
| 3 | +date: 2025-01-20 10:00:00 |
| 4 | +author: loongs-zhang |
| 5 | +--- |
| 6 | + |
| 7 | +# Hook Overview |
| 8 | + |
| 9 | +## Why hook? |
| 10 | + |
| 11 | +After a `Coroutine::resume_with`, a coroutine may occupy the scheduling thread for a long time, thereby slowing down |
| 12 | +other coroutines scheduled by that scheduling thread. To solve this problem, we introduce hook, which automatically |
| 13 | +suspends coroutines entering syscall and allow other coroutines to execute. |
| 14 | + |
| 15 | +The coroutine occupies scheduling threads for a long time in two scenarios: getting stuck in heavy computing or syscall. |
| 16 | +The following only solves the problem of getting stuck in syscall. |
| 17 | + |
| 18 | +Another problem is that `signals can interrupt the running syscall`, and the `preemptive` feature mechanism sends a |
| 19 | +large |
| 20 | +number of signals. In addition, most user code does not handle signals, if they directly use `open-routine-core` and |
| 21 | +enabling preemptive will lead to `catastrophic consequences`. |
| 22 | + |
| 23 | +## What is hook? |
| 24 | + |
| 25 | +Hook can modify or extend the behavior of existing code by inserting custom code at runtime, and even monitor, |
| 26 | +intercept, modify, and redirect system calls. Now, let's use an [example](https://github.com/loongs-zhang/link-example) |
| 27 | +to visually experience it. |
| 28 | + |
| 29 | +Assuming we have the following test code: |
| 30 | + |
| 31 | +```rust |
| 32 | +use std::time::{Duration, Instant}; |
| 33 | + |
| 34 | +#[test] |
| 35 | +fn test_hook() { |
| 36 | + let start = Instant::now(); |
| 37 | + std::thread::sleep(Duration::MAX); |
| 38 | + let cost = Instant::now().duration_since(start); |
| 39 | + println!("cost: {:?}", cost); |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +If we don't hook, this test would almost never end due to `std::thread::sleep(Duration::MAX)`, but with hook, we |
| 44 | +redirect the `nanosleep` syscall |
| 45 | +to [our custom code](https://github.com/loongs-zhang/link-example/blob/master/dep/src/lib.rs) `without change the test |
| 46 | +code`, and then the test |
| 47 | +will [end soon](https://github.com/loongs-zhang/link-example/actions/runs/12862762378/job/35858206179). |
| 48 | + |
| 49 | +<div style="text-align: center;"> |
| 50 | + <img src="/hook/docs/img/result-on-macos.png" width="50%"> |
| 51 | +</div> |
| 52 | + |
| 53 | +## How it works |
| 54 | + |
| 55 | +```mermaid |
| 56 | +sequenceDiagram |
| 57 | + Actor Your Project |
| 58 | + participant open-coroutine |
| 59 | + participant open-coroutine-hook |
| 60 | + participant open-coroutine-core |
| 61 | + |
| 62 | + Your Project ->> open-coroutine: depends on |
| 63 | + open-coroutine ->> open-coroutine-hook: depends on |
| 64 | + alt at compile time |
| 65 | + open-coroutine ->> open-coroutine: build open-coroutine-hook into dylib |
| 66 | + open-coroutine ->> open-coroutine: link open-coroutine-hook's dylib |
| 67 | + else runtime |
| 68 | + Your Project -->> Operation System: logic execute syscall |
| 69 | + alt what actually happened |
| 70 | + Your Project ->> open-coroutine-hook: redirect syscall to open-coroutine-hook's syscall mod |
| 71 | + open-coroutine-hook ->> open-coroutine-core: call open-coroutine-core's syscall mod |
| 72 | + open-coroutine-core ->> Operation System: execute fast syscall actually |
| 73 | + Operation System ->> open-coroutine-core: return syscall result and errno |
| 74 | + open-coroutine-core -->> Operation System: maybe execute fast syscall many times |
| 75 | + open-coroutine-core -->> open-coroutine-core: maybe modify syscall result or errno |
| 76 | + open-coroutine-core ->> open-coroutine-hook: return syscall result and errno |
| 77 | + open-coroutine-hook ->> Your Project: return syscall result and errno |
| 78 | + end |
| 79 | + Operation System ->> Your Project: return syscall result and errno |
| 80 | + end |
| 81 | +``` |
0 commit comments