Stopping the daemon while the RIS Live feed is flowing could panic with "send on closed channel" and skip the rest of the shutdown (#34).
Streamer.Stop cancels the stream and closes the handler queues under the streamer's write lock. The read loop checked for a stop only once per line, before parsing, so a stop landing after that check made it send to a closed queue. It now checks again under the read lock it already takes just before handing the message to the queues, and returns if the stream was stopped; under that lock, cancelled always means closed.
Stop now clears its cancel function and returns early when there is none, so a second call no longer closes the queues again (which also panicked), as its comment already promised.
TestStopBeforeMessageReachesQueues calls Stop from the raw handler, which runs on the read loop in exactly that gap, then calls Stop a second time. It covers both panics and uses only a local test server.
Disclosures:
Behaviour change: Stop before Start now does nothing; it used to close the queues of a streamer that had never started. Nothing relies on that.
Judgement call: the test forces the bad order every time from the raw handler instead of racing two goroutines and hoping to hit it.
Judgement call: the test sets the streamer's cancel function itself instead of calling Start, so it can wait for the stream to return.
Model: opus-5-5
Stopping the daemon while the RIS Live feed is flowing could panic with "send on closed channel" and skip the rest of the shutdown (https://git.eeqj.de/sneak/routewatch/issues/34).
- `Streamer.Stop` cancels the stream and closes the handler queues under the streamer's write lock. The read loop checked for a stop only once per line, before parsing, so a stop landing after that check made it send to a closed queue. It now checks again under the read lock it already takes just before handing the message to the queues, and returns if the stream was stopped; under that lock, cancelled always means closed.
- `Stop` now clears its cancel function and returns early when there is none, so a second call no longer closes the queues again (which also panicked), as its comment already promised.
- `TestStopBeforeMessageReachesQueues` calls `Stop` from the raw handler, which runs on the read loop in exactly that gap, then calls `Stop` a second time. It covers both panics and uses only a local test server.
Disclosures:
- Behaviour change: `Stop` before `Start` now does nothing; it used to close the queues of a streamer that had never started. Nothing relies on that.
- Judgement call: the test forces the bad order every time from the raw handler instead of racing two goroutines and hoping to hit it.
- Judgement call: the test sets the streamer's cancel function itself instead of calling `Start`, so it can wait for the stream to return.
Model: opus-5-5
Stop cancels the stream and closes the handler queues under the streamer's write lock, but the read loop only checked for a stop before parsing each line. A stop landing after that check made the loop send the message to a closed queue and panic. The loop now checks again under the read lock it already takes before handing the message to the queues, and returns if the stream was stopped.
Stop also clears its cancel function and returns early when there is none, so a second call no longer closes the queues again, as its comment already promised.
The new test calls Stop from the raw handler, which runs in exactly that gap, and then calls Stop a second time.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Stopping the daemon while the RIS Live feed is flowing could panic with "send on closed channel" and skip the rest of the shutdown (#34).
Streamer.Stopcancels the stream and closes the handler queues under the streamer's write lock. The read loop checked for a stop only once per line, before parsing, so a stop landing after that check made it send to a closed queue. It now checks again under the read lock it already takes just before handing the message to the queues, and returns if the stream was stopped; under that lock, cancelled always means closed.Stopnow clears its cancel function and returns early when there is none, so a second call no longer closes the queues again (which also panicked), as its comment already promised.TestStopBeforeMessageReachesQueuescallsStopfrom the raw handler, which runs on the read loop in exactly that gap, then callsStopa second time. It covers both panics and uses only a local test server.Disclosures:
StopbeforeStartnow does nothing; it used to close the queues of a streamer that had never started. Nothing relies on that.Start, so it can wait for the stream to return.Model: opus-5-5
Review passed.
Model: opus-5-5