Skip to content

aosp: wrap alarm() and make it use a thread-directed timer#11340

Open
rogerzanoni wants to merge 1 commit into
youtube:mainfrom
rogerzanoni:aosp-alarm
Open

aosp: wrap alarm() and make it use a thread-directed timer#11340
rogerzanoni wants to merge 1 commit into
youtube:mainfrom
rogerzanoni:aosp-alarm

Conversation

@rogerzanoni

Copy link
Copy Markdown
Collaborator

Bionic's implementation of alarm triggers a setitimer set with ITIMER_REAL making it a process-directed signal.

From the signal(7) manpage:
A process-directed signal may be delivered to any one of the threads
that does not currently have the signal blocked. If more than one of the
threads has the signal unblocked, then the kernel chooses an arbitrary
thread to which to deliver the signal.

Android's ART runtime/runtime.cc configures only a small set of signals:

void Runtime::BlockSignals() {
SignalSet signals;
signals.Add(SIGPIPE);
signals.Add(SIGQUIT);
signals.Add(SIGUSR1);
signals.Block();
}

SIGALRM is unblocked on the ART's main thread and it may catch the process-directed signal, never letting it reach cobalt/nplb calling threads, making it unreliable to wait for the signal using musl's implementation.

Fixes PosixClockNanosleepTest.ErrorEintrAbsoluteSleep, PosixClockNanosleepTest.ErrorEintrRelativeSleep and PosixNanosleepTests.ErrorEintr which were failing with a "signal never interrupted sleep" error.

Bug: 532068409

@rogerzanoni
rogerzanoni requested a review from a team as a code owner July 12, 2026 23:33
@rogerzanoni
rogerzanoni requested review from johnxwork and removed request for a team July 12, 2026 23:33
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Gemini Suggested Commit Message


android: Use thread-directed timer for alarm

On Android, Bionic's alarm implementation uses ITIMER_REAL, which
triggers process-directed signals. These signals can be intercepted
by the ART runtime's main thread where SIGALRM is unblocked,
preventing them from reaching the calling Cobalt thread. This causes
failures in NPLB tests that rely on signals to interrupt sleep.

This change introduces a wrapper for alarm in modular builds that
uses a per-thread POSIX timer with SIGEV_THREAD_ID. This ensures the
SIGALRM is directed specifically to the thread that requested it,
making signal delivery reliable.

Bug: 532068409

💡 Pro Tips for a Better Commit Message:

  1. Influence the Result: Want to change the output? You can write custom prompts or instructions directly in the Pull Request description. The model uses that text to generate the message.
  2. Re-run the Generator: Post a comment with: /generate-commit-message

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a thread-directed alarm() wrapper (__abi_wrap_alarm) for Android in modular Starboard to ensure reliable delivery of SIGALRM signals using thread-local POSIX timers. Feedback on the implementation suggests optimizing the case where seconds is 0 by bypassing timer creation, simplifying the gettid() retrieval since it is always available on Android, and switching from CLOCK_MONOTONIC to CLOCK_REALTIME to align with standard POSIX alarm() behavior during device suspend.

Comment thread starboard/shared/modular/starboard_layer_posix_unistd_abi_wrappers.cc Outdated
Comment thread starboard/shared/modular/starboard_layer_posix_unistd_abi_wrappers.cc Outdated
Comment thread starboard/shared/modular/starboard_layer_posix_unistd_abi_wrappers.cc Outdated
// A one-shot POSIX timer used to implement a thread-directed alarm()
struct ThreadAlarmTimer {
timer_t timer = nullptr;
bool created = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this necessary? Can we just check if timer is not nullptr instead?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed it

@andrewsavage1

Copy link
Copy Markdown
Contributor

@sacuff @jellefoks ptal

new_value.it_value.tv_sec = seconds;
struct itimerspec old_value = {};
if (timer_settime(thread_timer.timer, 0, &new_value, &old_value) != 0) {
// fallback

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can we log a warning?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

// A one-shot POSIX timer used to implement a thread-directed alarm()
struct ThreadAlarmTimer {
timer_t timer = nullptr;
bool created = false;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

+1

Bionic's implementation of alarm triggers a setitimer set with ITIMER_REAL
making it a process-directed signal.

From the signal(7) manpage:
  A  process-directed  signal  may  be  delivered to any one of the threads
  that does not currently have the signal blocked. If more than one of the
  threads has the signal unblocked, then the kernel chooses an arbitrary
  thread to which to deliver the signal.

Android's ART runtime/runtime.cc configures only a small set of signals:

void Runtime::BlockSignals() {
  SignalSet signals;
  signals.Add(SIGPIPE);
  signals.Add(SIGQUIT);
  signals.Add(SIGUSR1);
  signals.Block();
}

SIGALRM is unblocked on the ART's main thread and it may catch the
process-directed signal, never letting it reach cobalt/nplb calling threads,
making it unreliable to wait for the signal using musl's implementation.

Fixes PosixClockNanosleepTest.ErrorEintrAbsoluteSleep,
PosixClockNanosleepTest.ErrorEintrRelativeSleep and
PosixNanosleepTests.ErrorEintr which were failing with a "signal never
interrupted sleep" error.

Bug: 532068409
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.

3 participants