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

Possibility for a deadlock #29

Open
gfzabarino opened this issue Apr 5, 2018 · 4 comments
Open

Possibility for a deadlock #29

gfzabarino opened this issue Apr 5, 2018 · 4 comments

Comments

@gfzabarino
Copy link

gfzabarino commented Apr 5, 2018

Hi! This library looks really great and I'm considering to include it into a new project. However I have a theory question I'd like to get an answer to before doing that. I was wondering if the following scenario was possible:

  1. async something, which gets executed in the "async" concurrent queue, which runs in thread A.
  2. Inside thread A you await for something, which locks thread A, and that something runs on thread B.
  3. On thread B something else is awaited, which causes thread B to be locked as well, and that something is dispatched to the "async" concurrent queue. Then, GCD chooses thread A to run that, either because it ran out of threads from its internal thread pool, or because it assumes it will unlock eventually, continuing with the dispatched block after that happens.
  4. Thread B will be awaiting for something that got dispatched to thread A (the last awaited async block), but thread A is also awaiting for thread B to resolve its promise. Then there's a deadlock and there's no way of getting out of it.

Thank you in advance, and as I'm sure something like StackOverflow would be better to ask this kind of questions, I also know there's no better person to answer it than the creator of the framework himself.

@langtutheky
Copy link

Yes, the scenario that you described is completely possible. This is especially true for nesting async/wait. The source code use DispatchSemaphore, and call wait(timeout: . distantFuture), which certainly means this library can result in deadlocks. This problem could be mitigated by overloading another method such await(timeout: DispatchTime) to allow customization on how long should the thread be locked for.

@yannickl
Copy link
Owner

yannickl commented Aug 8, 2018

Hi @gfzabarino, and sorry for the very late. As @langtutheky said, the scenario you described can indeed happened. I don't know how the Javascript or C# runtimes solve this case.

The easiest solution is to put a timeout to the the semaphore waiting for this is not really beautiful...

@langtutheky
Copy link

langtutheky commented Aug 8, 2018

@yannickl Async/Await can be easily implemented using a single-threaded/non-blocking model at the language level as in the case of Javascript and C#. Whenever an async block is enter, the compiler/interpreter will create an internal serial queue, wrapping each statement until the next "await" into a closure and push it to the queue. It then serially executes each closure, and pass the return value of the last closure to the next one. All of this happens in a single thread without any blocking. This same technique can be applied for Promises and Javascript's Generators. I have seen lots of Promises implementation on iOS, and sadly most of them use multi-threading/blocking model which is totally unnecessary. Promises's API is purely functional, hence, it can easily implement single-threaded/non-blocking model. But Async/Await and Generators introduce special syntax which helps the code to "look and feel" synchronous, which is impossible to implement on a single thread without compiler/interpreter's interference. Until Async/Await is implemented, probably in Swift 5, there is not much we can do about this issue. With that said, putting a timeout is the best solution right now. Having an overloading await(timeout: DispatchTime) would be nice in cases of long-running task or I/O tasks (downloading/uploading).

@nonameplum
Copy link

nonameplum commented Oct 24, 2018

@langtutheky do you have and an example of a library that utilizes single-threaded/non-blocking model?
I would like to learn about this more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants