Opened 5 years ago

Closed 3 years ago

#15193 closed bug (fixed)

pselect() is not interrupted by signal

Reported by: simonsouth Owned by: korli
Priority: normal Milestone: R1/beta3
Component: System/POSIX Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Platform: x86-64

Description

POSIX's pselect() function is meant to block until either a file descriptor becomes ready for I/O or a signal is received. Haiku's implementation currently fails in the latter case, seeming to enter an infinite loop instead of returning when a signal arrives.

I'm attaching a program that demonstrates this. The program

  • Attaches a handler for the SIGCHLD signal, which is sent automatically when a child process terminates;
  • Blocks SIGCHLD, causing the signal to be held by the OS when it arrives;
  • Spawns a child process that exits immediately, raising SIGCHLD; and
  • Calls pselect() with an empty signal mask (temporarily unblocking SIGCHLD), waiting for STDIN to become ready.

The program should exit immediately when it's run, as the SIGCHLD signal should interrupt pselect() right away without a chance for the user to enter anything. Linux shows the correct behaviour:

Child process is exiting
Waiting for Enter or signal...
SIGCHLD received
pselect() returned -1: Interrupted system call (4)

On Haiku the program hangs at pselect(), with the thread consuming about 30% of the CPU's time:

Child process is exiting
Waiting for Enter or signal...

Pressing Enter causes the program to exit, so pselect() is correctly monitoring the file descriptor.

From the kernel debugger the thread seems to get stuck in a loop when the signal arrives, continually re-executing common_select(). Stepping through part of the function, it does seem to correctly recognize the SIGCHLD signal has arrived, and returns B_INTERRUPTED (or tries to).

My theory is the thread is then left in an "interrupted system call" state, triggering some other part of the system to restart the call automatically. But because pselect() is meant to be interrupted by signals this prevents it from ever making progress or returning to its caller. I haven't been able to verify this, though.

Any advice on where I should be looking next to debug this?

Attachments (2)

pselect-test.c (1.6 KB ) - added by simonsouth 5 years ago.
Sample program demonstrating pselect()'s incorrect behaviour
pselect-kdl.png (43.3 KB ) - added by simonsouth 5 years ago.
KDL backtrace from the program, when the pselect() call appears to be stuck looping

Download all attachments as: .zip

Change History (10)

by simonsouth, 5 years ago

Attachment: pselect-test.c added

Sample program demonstrating pselect()'s incorrect behaviour

comment:1 by simonsouth, 5 years ago

This is in hrev53259 on x86_64, by the way.

by simonsouth, 5 years ago

Attachment: pselect-kdl.png added

KDL backtrace from the program, when the pselect() call appears to be stuck looping

comment:2 by waddlesplash, 5 years ago

This may be related to a design flaw in our select() implementation. There was a patch from a developer years ago to rectify that but it was not organized properly; I have it now on Gerrit (https://review.haiku-os.org/c/haiku/+/897) and some offline work here also. Guess it's time I finished it up.

comment:3 by simonsouth, 5 years ago

Thanks, waddlesplash. Let me know if I can help out with this.

comment:4 by korli, 3 years ago

Owner: changed from nobody to korli
Status: newassigned

comment:5 by korli, 3 years ago

Milestone: UnscheduledR1/beta3

comment:6 by korli, 3 years ago

Resolution: fixed
Status: assignedclosed

Fixed in hrev54892

comment:7 by korli, 3 years ago

Resolution: fixed
Status: closedreopened

Reverted in hrev54895

comment:8 by korli, 3 years ago

Resolution: fixed
Status: reopenedclosed

The amended fix was applied in hrev54896

Note: See TracTickets for help on using tickets.