-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Document that all IO operations, including print, are asynchronous #13450
Comments
I would think that it would be expected that anything involving IO such as print might yield. |
Hmm, I couldn't find anything in the documentation that would indicate this is meant to be asynchronous. My whole experience with Julia is that by default methods that might take a long time like file IO are blocking and synchronous, unlike say Node, so this really seems like a bug to me. If you want to just document it as asynchronous, that's ok, just please do it in big bold letters! |
As a use case, I was implementing a simple resource pool, and there was a block of code I was assuming was atomic. I would be notified a resource was available, and I would then obtain a "lock" on that resource by removing it from the pool. It's very trivial code to write, but it became a nightmare when for some reason it was behaving very stochastically. It turns out it was because the block was not atomic at all because an innocent "print" line was a "yield" in disguise. |
All IO operations yield. libuv, the same library that handles async IO for Node, is also used in Julia whenever |
Ah I see. Thanks for clarifying. I think that documentation for a point like this is critical. The Node api makes the async nature of such calls blindingly obvious by requiring you to provide callbacks. In ES6, yield can only be called within special generator functions which are distinctly marked separately from regular functions with a star: "function*()". Another example is C# where you can only call "await" from within a function marked "async" and the norm furthermore is to name such functions xxxAsync(). The danger with hidden yields is that as a developer it becomes increasingly difficult to easily eye code and determine whether a series of statements will be executed atomically or not which can lead to subtle bugs. Obviously, in Julia it is not idiomatic to use callbacks everywhere, and maybe for IO operations, we can just try to remember that they are async as well as not hide them too deeply within other function stacks. There are tradeoffs with any approach. But please put better documentation! |
If you'd like to submit a pull request with suggested changes to the documentation, we would certainly consider and appreciate it. |
@malmaud Is it for all I/O or only Text I/O? |
All I/O. In fact, anything that might block is done asynchronously. |
Ok, so is this sufficient - #15238 |
There is a discussion on julia-users about whether this is true of file I/O, which uses |
See comments on #15091 |
This bug is very subtle and took me a couple of hours to trace down to being caused by the "print" method. Basically, when writing asynchronous code using tasks, there is an expectation that your code only yields at well defined points, such as when calling "wait" or "yield". It seems that "print" also can cause your code to yield execution.
The below function fails in Julia 0.3.12:
But if you comment out the print statement, it will pass.
The text was updated successfully, but these errors were encountered: