Repository navigation
Conversation
coot
force-pushed
the
coot/racy-by-label
branch
from
November 13, 2026 16:19
1f42655 to
1c9bc01
Compare
The default implementation of `withAsyncWithUnmask` (used by IOSim, but
not IO), didn't restore masking state the same way `async` and `base`
packages do. This only matters if the `withAsyncWithUnmask` is
called when exception are `Unmasked`. The correct implementation
(below) uses `restore` in
```hs
withAsyncWithUnmask action inner = mask $ \restore -> do
a <- asyncWithUnmask (\unmask -> restore (action unmask))
restore (inner a)
`finally` uninterruptibleCancel a
```
to restores the original `Unmasked` state.
The buggy implementation:
```hs
withAsyncWithUnmask action inner = mask $ \restore -> do
a <- asyncWithUnmask action
restore (inner a)
`finally` uninterruptibleCancel a
```
when called with exceptions `Unmasked`, will run `action` in
`InterruptibleMasked` state instead.
There's not difference between the two implementations when the function
is called when exceptions are masked or uninterruptibly masked.
The commit includes tests for `IO` and `IOSim` instances.
IOSimPOR can now select the threads which take par ti in race discovery by their label with the following rules: * threads must be started by one of `forkLabelledIO` or `asyncLabelled`, `withAsyncLabelled` and friends - this makes sure the thread label is available in `IOSim` when a thread is created rather than set by `labelThisThread` when it is scheduled * racy flag is sticky, e.g. threads started by a thread that are part of race discovery are part of the race discovery. You need to set the new `explorationRacyByLabel` field of `ExplorationOptions`, either directly or by using one of the two combinators: * `withRacyMainThread` - IOSimPOR will make all threads part of schedule exploration (this wasn't possible before) * `withRacyByLabel` - by passing a callback the simulation can select which threads will be part race exploration The test-suite is using now internal API, and thus depends on `io-sim` sources directly. This way we can keep internal API unexposed to the user. Almost all `IOSimPOR` tests are using now `withRacyMainThread` - for that reason we had to drop `withNumTests 1000` from two tests. New tests are included for labelled functions.
coot
force-pushed
the
coot/racy-by-label
branch
from
November 14, 2026 21:13
1c9bc01 to
553d462
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a more control over which threads are part of schedule exploration. It relies on two API changes:
explorationRaceByLabelcallback field forExplorationOptions(with two helperswithRacyMainThreadandwithRaceByLabelforkLabelledIO,asyncLabelled,withAsyncLabelled& friends, which must be used so the label is available when forked thread is created rather than altered when the forked read is being executed.An alternative design where
IOSimThreadIdis no longer a type with two constructorsRacyThreadIdandThreadId, which wouldn't require speciallforkLabelledIOAPI is possible, but it is significant change to theIOSimPORAPI, and thus I decided to not pursue it. The advantage of the implemented design is simplicity ofIOSimPORchanges (ForkcarriesThreadLabelfield), all other changes are peripheral toIOSimPORrace discovery logic, plus changes toMonadForkandMonadAsync.