-
Notifications
You must be signed in to change notification settings - Fork 1.7k
IOSink.flush() - Bad state: StreamSink is bound to a stream #25277
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
Comments
The flush method does not sent any signals to the io system, or push data through any faster. It just returns a future that completes when there is no data buffered in the IOSink object. It essentially just adds an empty stream to the IOSink, and signals when this empty stream is completed. Flush does not push data any faster, it just reports when there is no data buffered in this object. So, just as only one stream can be added to an IOSink (or any StreamConsumer) at a time, only one flush operation can be outstanding at a time. |
This message extends the earlier comment, with more details about how flush() could, in some cases, signal the IOSink to move data. IOSink is built upon the simpler class StreamConsumer, which can only take streams of data, one at a time, and consume them. At the end of each stream, it gets a done event from that stream, which it COULD use as a signal to flush stuff more aggressively into or through whatever its target is. Then, it completes the future it returned when the stream was added, to signal it is done and ready to take another stream. So this future completing COULD indicate that the data has been fully processed downstream, in some sense. The synchronous add() method is added to this object that only supports adding a stream, by adding a hidden internal streamController, and adding its stream to the StreamConsumer. Sequential add() calls just have their data all fed into this streamController, and this hidden internal stream is closed only when the whole IOSink is closed, or when addStream() or flush() is called on it. The added stream is stored, the hidden internal stream is closed, and when the StreamConsumer is ready to take a new stream, the added stream is added. So it is possible that calling flush(), by closing the internal stream, may signal to the downstream StreamConsumer that it should "flush" in some way. But just as only one added stream can be active, only one flush can be active, since it acts as an added stream. |
The exception thrown above is from a call to IOSink.add so it seems like you can not call add whilst a flush operation is outstanding. Suggest documenting this and improving the exception message if possible. For my own application I now see that I don't need to call the flush method at all. I was used to having to call flush() in python because python does some internal buffering before calling the underlying os write(). If you were implementing a db then you would want to be able to call fsync on a stream which is not possible. There is a closed bug about it which seems to also be confused about what the flush method is doing: #8794 |
…e since it will not serve to optimize the buffer. It is also called inside a stream subscription that is it surely not good and moreover may cause a `Bad state: StreamSink is bound to a stream` in this context
This code writes to a file and calls flush() a lot. It does not wait for the flush future to complete. The intent is to signal the os to write out the data so it becomes visible to other processes which have the file open.
Running this in dart produces the crash:
Am I using the wrong API for this or is it a bug?
The text was updated successfully, but these errors were encountered: