DUE TO SPAM, SIGN-UP IS DISABLED. Goto Selfserve wiki signup and request an account.
...
Design Issues
NOTE: The issue address addressed in this paragraph is covered by Issue 619 has been corrected in the code base through a series of changes culiminating int PR 733. This discussion still has value, however, as a warning for things that one needs to take into consideration when designing logic within the OS.
...
Should we return -ECANCEL/-EINTR for both? Or only for ithe second? I think both should work the same: For both the semaphore wait should be terminated and correct error should be returned.
(Brief) Mutual Exclusion Semaphores
If the API requires returning EINTR if a signal is received, we should return the error. This is required in many POSIX interfaces and don't see how you could avoid that. However, the mutual exclusion semaphores are the just there for the correctness in the design. There is seldom any real competitor for the exclusion semaphore so, in general, they do not block and, hence, would never generate any error.
...
But if during the that brief moment while the thread is blocked, a signal is received, I think that it is correct to return -EINTR. This is not so critical only because such an event it is rare. But the specification requires it so we should do it.
And there are situations were the task may block for a very long time, even indefinitely, on a mutual exclusion semahore. Consider the following scenario: A driver that reads data could have a sequence like this:
- Get exclusive access to the driver by taking a semaphore
- Wait on a semaphore for data (might be a long time)
- Release the mutual exclusion semaphore.
Now suppose there are two applications, Task A and Task B, that open the driver and try to read from it. The first, Task A, will get the mutual exclusion semaphore at (1) and then will hang waiting for data at (2). It may have to wait for a very long time to receive data. When re-entered by the second, Task B, will hang at (1) also for very long time. Task B is effectively queued and cannot event begin its wait on the signaling semphore until Task B receives its data and releases the mutual exclusion semaphore. This is normal behavior and exactly, how this kind of driver is supposed to work.
But now suppose that Task B receives a signal interrupt or a cancellation event while waiting on the mutual exclusion semaphore. It MUST terminate the wait and return -EINTR or -ECANCEL immediately. Task A may never receive data and if that action is not taken, the signal interrup or cancellation event is lost and the functionality has failed.
The ECANCELED error is ABSOLUTELY critical to return under any circumstance. That cancellation notification is received only once and it if is ignored, then the thread will not cancel it will continue to run. It really must return immediately with ECANCELED for the cancellation to work quickly and reliably, where ever ECANCELED is detected. Ignoring it is a hard bug in any case.
The signaling semaphores are a little different story. They may block for a very long time, for example, waiting for the receipt of data that will never come. For example, a read from a serial port will hang indefinitely if nothing is received on the serial port. So if a signal is received or if the thread is canceled, then it is essential to terminate the semaphore wait and return the error condition. We should have no difference of opinion on that.
...
When to Return ECANCELED
The ECANCELED error is ABSOLUTELY critical to return under any circumstance. That cancellation notification is received only once and it if is ignored, then the thread will not cancel it will continue to run. It really must return immediately with ECANCELED for the cancellation to work quickly and reliably, where ever ECANCELED is detected. Ignoring it is a hard bug in any case.
Signaling Semaphores
The signaling semaphores are a little different story. They may block for a very long time, for example, waiting for the receipt of data that may never come. For example, a read from a serial port will hang indefinitely if nothing is received on the serial port. So if a signal is received or if the thread is canceled, then it is essential to terminate the semaphore wait and return the error condition. We should have no difference of opinion on that.
There is really no difference in the actions that must be taken if a signal is received of if the task is canceled. Both mutual exclusion semaphores and signaling semaphores should wake up and return the error condition. The only real differences is that mutual exclusion semaphores either do not block or, if they do, the do not block as long.
(Long) Mutual Exclusion Semaphores and Serialization
There are situations were the task may block for a very long time, even indefinitely, on a mutual exclusion semaphore. Consider the following scenario: A driver that reads data could have a sequence like this:
- Get exclusive access to the driver by taking a semaphore
- Wait on a signaling semaphore for data (might be a long time)
- Release the mutual exclusion semaphore.
Now suppose there are two applications, Task A and Task B, that open the driver and try to read from it. The first, Task A, will get the mutual exclusion semaphore at (1) and then will hang waiting for data at (2). It may have to wait for a very long time to receive data. When re-entered by the second, Task B, it will hang at (1) also for very long time. Task B is effectively queued and cannot event begin its wait on the signaling semphore until Task A receives its data and releases the mutual exclusion semaphore. This is normal behavior and exactly, how this kind of driver is supposed to work: This use of mutual exclusion impelements serialization of I/O.
But now suppose that Task B receives a signal interrupt or a cancellation event while waiting on the mutual exclusion semaphore. It MUST terminate the wait and return -EINTR or -ECANCEL immediately. Task A may never receive data and if that action is not taken, the signal interrup or cancellation event is lost and the functionality has failed.
When to Return EINTR
Returning EINTR really only applies to read() and write() (and open()) functions as covered by Issue #669 . In other places, EINTR can be ignored. open() and close() should also return EINTR. But I don't think that is very meaningful for close() since most people ignore the return value from close(). But, on the other hand, ECANCELED can never be ignored under any condition.
...