feat: xev Dynamic API + gitignore updates for Shadow support#704
feat: xev Dynamic API + gitignore updates for Shadow support#704
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the Zig codebase to use libxev’s Dynamic API so the runtime can select the best available I/O backend (io_uring vs epoll), improving portability across Linux kernel versions and compatibility with Shadow. It also updates .gitignore to exclude additional local/tool-generated artifacts.
Changes:
- Switched
@import("xev")usages to@import("xev").Dynamicacross node, network, and CLI code. - Added a
detectBackend()helper and invoked it early in CLI startup and node test initialization. - Updated
.gitignoreto ignorezig-pkg/, Shadow outputs, and.idea/.
Reviewed changes
Copilot reviewed 11 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| pkgs/node/src/utils.zig | Introduces detectBackend() and moves node code to xev.Dynamic. |
| pkgs/node/src/testing.zig | Calls backend detection before initializing the event loop in tests. |
| pkgs/node/src/node.zig | Switches xev import for tests to xev.Dynamic. |
| pkgs/node/src/lib.zig | Re-exports detectBackend for external callers (CLI). |
| pkgs/node/src/clock.zig | Switches xev import to xev.Dynamic. |
| pkgs/network/src/mock.zig | Switches to xev.Dynamic and adds backend detection in tests. |
| pkgs/network/src/interface.zig | Switches xev import to xev.Dynamic. |
| pkgs/network/src/ethlibp2p.zig | Switches xev import to xev.Dynamic. |
| pkgs/cli/src/node.zig | Switches xev import to xev.Dynamic. |
| pkgs/cli/src/main.zig | Calls node_lib.detectBackend() early during CLI startup. |
| build.zig | Notes that xev backend override is no longer needed. |
| .gitignore | Ignores zig-pkg/, Shadow outputs, and JetBrains IDE files. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// On single-backend platforms (macOS/kqueue) this is a no-op. | ||
| pub fn detectBackend() void { | ||
| if (@hasDecl(xev, "detect")) { | ||
| xev.detect() catch @panic("no available xev backend"); |
There was a problem hiding this comment.
xev.detect() failures are turned into a generic @panic("no available xev backend"), which drops the underlying error and makes field debugging hard (e.g., missing io_uring support vs. permission issues). Consider including the caught error (e.g., @errorName(err) / {any}) in the panic message or returning an error instead of panicking so callers can surface it consistently.
| xev.detect() catch @panic("no available xev backend"); | |
| xev.detect() catch |err| std.debug.panic("no available xev backend: {s}", .{@errorName(err)}); |
| if (@hasDecl(xev, "detect")) xev.detect() catch @panic("no available xev backend"); | ||
| var loop = try xev.Loop.init(.{}); |
There was a problem hiding this comment.
This if (@hasDecl(xev, "detect")) xev.detect() ... backend-detection snippet is duplicated in multiple tests in this file. Consider factoring it into a small local helper (e.g., detectBackendOrPanic()), so the behavior/error handling stays consistent and future changes only need to be made once.
| if (@hasDecl(xev, "detect")) xev.detect() catch @panic("no available xev backend"); | ||
| var loop = try xev.Loop.init(.{}); | ||
| defer loop.deinit(); |
There was a problem hiding this comment.
This backend detection line duplicates the same xev.detect() snippet used earlier in this file. To reduce repetition (and keep the panic/error message consistent), consider extracting the detection into a single helper and calling it from each test before xev.Loop.init.
| std.debug.print("opts={any} genesis={d}\n", .{ opts.args, genesis }); | ||
|
|
||
| // Detect the best available I/O backend (io_uring or epoll on Linux). | ||
| node_lib.detectBackend(); |
There was a problem hiding this comment.
node_lib.detectBackend() currently panics on failure (see utils.detectBackend), which bypasses the CLI’s normal ErrorHandler flow and will crash the process with a generic message. Consider changing detection to return an error and handling/logging it here (similar to the xev.Loop.init error handling below) so startup failures are reported consistently.
| node_lib.detectBackend(); | |
| node_lib.detectBackend() catch |err| { | |
| ErrorHandler.logErrorWithOperation(err, "detect I/O backend"); | |
| return err; | |
| }; |
Switch from compile-time xev backend selection to the Dynamic API, which probes io_uring at runtime and falls back to epoll. This is needed for Shadow network simulator (no io_uring support) but also makes the binary portable across Linux kernel versions.
bb009e5 to
ddcfd5c
Compare
Summary
zig-pkg/cache, Shadow simulator outputs, and IDE filesDetails
xev Dynamic API
All
@import("xev")changed to@import("xev").Dynamic, which probes io_uring at runtime and falls back to epoll. AdetectBackend()helper inutils.zigis called early in main and in test setup.gitignore
zig-pkg/— local Zig package cache (should not be committed)shadow.yaml,shadow.data/— generated bylean-quickstart/run-shadow.sh.idea/— JetBrains IDE filesTest plan
lean-quickstart/run-shadow.sh