Skip to content

Add proc_raise_interval2 syscall#6309

Draft
aeryz wants to merge 2 commits intowasmerio:mainfrom
aeryz:add/proc-raise-interval2
Draft

Add proc_raise_interval2 syscall#6309
aeryz wants to merge 2 commits intowasmerio:mainfrom
aeryz:add/proc-raise-interval2

Conversation

@aeryz
Copy link
Copy Markdown
Contributor

@aeryz aeryz commented Mar 16, 2026

Upon investigating #5907, I realized that proc_raise_interval is not sufficient for a complete setitimer implementation. The details are explained in depth here.

Under the issue, @zebreus suggested that we introduce a new syscall called proc_raise_interval2 which closely follows setitimer.

This PR is an attempt to add it. Since I'm new here and don't know the process of introducing a new API, I wanted to create the draft PR and show how would it look like. In addition to this PR, here are the changes done to other repos:

  1. wasix-libc: Generated the C bindings
  2. WASI: Added the witx definitions

Additionally, proc_raise_interval syscall was previously missing the support for repetition which is now supported for both proc_raise_interval and proc_raise_interval2.

Fixes: #6284

Also note that, due to the sync nature of how the signal handling works, the runtime only checks for the intervals during syscalls. This means on CPU-heavy applications, the signal timer will not work properly (it will never execute before the interval but might take longer). We can note this as a known limitation for now and in the future work on async signal handling.

If we agree on adding this syscall, I will also add some e2e tests.

Signed-off-by: aeryz <abdullaheryz@protonmail.com>
Copy link
Copy Markdown
Contributor

@zebreus zebreus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do a proper review once this is no longer a draft. @Arshia001 @theduke what do you think of this change?

Please make sure this does not break existing use of proc_wasix_interval. When you add the tests for proc_raise_interval and proc_raise_interval2 add them in lib/wasix/tests/wasm_tests and not in tests/wasix.

Also the proc_raise_interval2 implementation should live in its own file in syscalls/wasix.

Usually we make the old version just forward to the new implementation of the syscall but this might be hard here given the new signature reads the values from memory. Maybe create a shared helper or adjust the signature?

I agree that we should add documentation on the limitations of our signal handling implementation,. For now a comment to the syscall implementation is probably good enough.

@marxin marxin requested review from Arshia001 and theduke March 17, 2026 08:26
Copy link
Copy Markdown
Collaborator

@theduke theduke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

The direction makes sense.

Needs some modifications.

} else {
zero
},
value: __wasi_timeval_t {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are sticking to Linux semantics of setitimer here, which I reckon we should, then the old value is supposed to be the time until the next trigger time, not the originally configured time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good catch! My understanding was when a timer is hit, the value becomes interval and interval stays as is. It's actually true but I missed the part where value always gives the time until the next trigger time.
Relevant info: posix settimer, setitimer.

I'll return the value - now - last_signal instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here

) -> Result<Errno, WasiError> {
println!("called regular raise");
let env = ctx.data();
let interval = match interval {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As @zebreus said, an we implement a helper function that uses Rust types, and make both old and new implementation use the helper, to avoid duplication?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah yeah, I wanted to open a PR to have a minimal PoC on the new syscall. Since we are good with the API now, I will do the refactors and add the tests to complete the PR.

Copy link
Copy Markdown
Contributor Author

@aeryz aeryz Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Giving it some more thought, I think the functions are currently already implemented in a way that the main logic is shared. Note that the shared logic is:

  1. timer is set with the given signal
  2. previous timer is removed when the timer.value is 0
    Both of these are already implemented by WasiProcess::signal_interval. The functions differ in:
  3. proc_raise_interval works with millisecond timestamps, but proc_raise_interval2 works with itimerval
  4. proc_raise_interval2 makes use of the old timer.
    These are already implemented seperately and the only duplicate part is WasiEnv::do_pending_operations which I would say it's good to keep it explicit per syscall unless the legacy implementation is directly forwarded to the new implementation.

And in terms of the use of proper Rust types. I kept the fields of __wasi_timeval_t private and make it convertible to Duration. So if anyone wants to do any meaningful thing with __wasi_timeval_t, they would have to convert it to Duration first. And our internal Rust types and the signal interval related functions all use Durations. Please let me know if you see a possible footgun.

} else {
Some(Duration::from_secs(tv.sec) + Duration::from_micros(tv.usec))
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a test/tests in the tests/wasix test suite.

The pattern of existing tests should be easy to emulate.
Note: you'll need wasixcc ( https://github.com/wasix-org/wasixcc )

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests are added under libc_tests for alarm and setitimer.

}

fn timeval_to_duration(tv: __wasi_timeval_t) -> Option<Duration> {
if tv.sec == 0 && tv.usec == 0 {
Copy link
Copy Markdown
Collaborator

@theduke theduke Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this can overflow the range of Duration.
Should probably return an error here, so the caller gets back an Errno::INVAL.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah better to use checked_add here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistent time unit for intervals in signal handling

3 participants