Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix race condition from CancelAll #5

Merged
merged 1 commit into from
Jan 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
# Changelog
All notable changes to this project will be documented in this file.
# Change Log

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
[Unreleased]: https://github.com/mec07/rununtil/compare/v0.2.0...HEAD
## [0.2.2] - 2020-01-29

### Fixed

- Fix race condition in CancelAll

## [0.2.0] - 2019-06-12
[0.2.0]: https://github.com/mec07/rununtil/compare/v0.1.0...v0.2.0

### Fixed

- There was a problem with sending a kill signal to a nonblocking main function. This has been fixed by providing the CancelAll method.

### Changed

- Deprecate: functions KillSignal, Signals, and Killed
- Replace them with: AwaitKillSignal, AwaitKillSignals and CancelAll

### Fixed
- There was a problem with sending a kill signal to a nonblocking main function.
This has been fixed by providing the CancelAll method.

## [0.1.0] - 2019-06-12
[0.1.0]: https://github.com/mec07/rununtil/compare/v0.0.1...v0.1.0
### Changed
- There are now RunnerFunc and ShutdownFunc function types to clarify the usage of this library (backwards incompatible change)

### Added

- Implemented the rununtil.Killed method, which allows you to test a function that uses rununtil.KillSignal

### Changed

- There are now RunnerFunc and ShutdownFunc function types to clarify the usage of this library (backwards incompatible change)

## [0.0.1] - 2019-06-05
[0.0.1]: https://github.com/mec07/rununtil/releases/tag/v0.0.1

### Added
- initial commit of rununtil library

- initial commit of rununtil library

26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,29 @@
Go library to run a function until a kill signal is recieved.

See the docs: https://godoc.org/github.com/mec07/rununtil

## Changelog

The [CHANGELOG.md](./CHANGELOG.md) file tracks all of the changes and each release.
We are managing it using the helpful [changelog-tool](https://github.com/ponylang/changelog-tool).
On Mac you can install it with brew: `brew install kaluza-tech/devint/changelog-tool`.
On linux (or any other platform) you have to install the pony language.
Then just follow the instructions on the github page for installing the changelog-tool:
https://github.com/ponylang/changelog-tool#installation

The use of the tool is straightforward.
To create a new changelog (don't run this in this repo because then you'll replace the current changelog with a new one!):
```
changelog-tool new
```
To start recording a new entry:
```
changelog-tool unreleased -e
```
The `-e` means update the changelog file in place.
Then manually edit the changelog to add your changes in the unreleased section.
When you're ready you can then "release" it by executing:
```
changelog-tool release 0.0.1 -e
```
Replace `0.0.1` with the new version.
12 changes: 3 additions & 9 deletions rununtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,22 +95,17 @@ type canceller struct {

func (canc *canceller) addChannel(key string, c chan struct{}) {
canc.mux.Lock()
defer canc.mux.Unlock()
canc.signals[key] = c
canc.mux.Unlock()
}

func (canc *canceller) removeChannel(key string) {
canc.mux.Lock()
delete(canc.signals, key)
canc.mux.Unlock()
}

func (canc *canceller) cancelAll() {
canc.mux.Lock()
defer canc.mux.Unlock()
for key := range canc.signals {
close(canc.signals[key])
delete(canc.signals, key)
}
canc.mux.Unlock()
}

var globalCanceller canceller
Expand Down Expand Up @@ -146,7 +141,6 @@ func AwaitKillSignals(signals []os.Signal, runnerFuncs ...RunnerFunc) {
finish := make(chan struct{})
uuid := uuid.New()
globalCanceller.addChannel(uuid.String(), finish)
defer globalCanceller.removeChannel(uuid.String())

for _, runner := range runnerFuncs {
shutdown := runner()
Expand Down
10 changes: 10 additions & 0 deletions rununtil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,19 @@ func TestRununtilCancelAll_MultipleTimes(t *testing.T) {
}

func TestRununtilCancelAll_Threadsafe(t *testing.T) {
var hasBeenKilledVec [100]bool
for idx := 0; idx < 100; idx++ {
cancel := rununtil.Killed(helperMakeMain(&hasBeenKilledVec[idx]))
cancel()
rununtil.CancelAll()
}
// yield control back to scheduler so that killing can actually happen
time.Sleep(time.Millisecond)
for idx, hasBeenKilled := range hasBeenKilledVec {
if !hasBeenKilled {
t.Fatalf("expected main to have been killed: %d", idx)
}
}
}

// Annoyingly this test has to be run by itself to actually fail...
Expand Down