> On Sep 12, 2017, at 12:31 PM, John McCall via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
>> 
>> On Sep 12, 2017, at 2:19 AM, Pierre Habouzit via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> On Sep 11, 2017, at 9:00 PM, Chris Lattner via swift-evolution 
>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>> 
>>> On Sep 4, 2017, at 12:18 PM, Pierre Habouzit <phabou...@apple.com 
>>> <mailto:phabou...@apple.com>> wrote:
>>>> Something else I realized, is that this code is fundamentally broken in 
>>>> swift:
>>>> 
>>>> actor func foo()
>>>> {
>>>>     NSLock *lock = NSLock();
>>>>     lock.lock();
>>>> 
>>>>     let compute = await someCompute(); <--- this will really break `foo` 
>>>> in two pieces of code that can execute on two different physical threads.
>>>>     lock.unlock();
>>>> }
>>>> 
>>>> 
>>>> The reason why it is broken is that mutexes (whether it's NSLock, 
>>>> pthread_mutex, os_unfair_lock) have to be unlocked from the same thread 
>>>> that took it. the await right in the middle here means that we can't 
>>>> guarantee it.
>>> 
>>> Agreed, this is just as broken as:
>>> 
>>> func foo()
>>> {
>>>     let lock = NSLock()
>>>     lock.lock()
>>> 
>>>     someCompute {
>>>         lock.unlock()
>>>     }
>>> }
>>> 
>>> and it is just as broken as trying to do the same thing across queues.  
>>> Stuff like this, or the use of TLS, is just inherently broken, both with 
>>> GCD and with any sensible model underlying actors.  Trying to fix this is 
>>> not worth it IMO, it is better to be clear that they are different things 
>>> and that (as a programmer) you should *expect* your tasks to run on 
>>> multiple kernel threads.
>>> 
>>> BTW, why are you using a lock in a single threaded context in the first 
>>> place??? ;-)
>> 
>> I don't do locks, I do atomics as a living.
>> 
>> Joke aside, it's easy to write this bug we should try to have the 
>> compiler/analyzer help here for these broken patterns.
>> TSD is IMO less of a problem because people using them are aware of their 
>> sharp edges. Not so much for locks.
> 
> Maybe we could somehow mark a function to cause a warning/error when directly 
> using it from an async function.  You'd want to use that on locks, 
> synchronous I/O, probably some other things.

Well the problem is not quite using them (malloc would e.g. and there's not 
quite a way around it), you don't want to hold a lock across await.

> 
> Trying to hard-enforce it would pretty quickly turn into a big, annoying 
> effects-system problem, where even a program not using async at all would 
> suddenly have to mark a ton of functions as "async-unsafe".  I'm not sure 
> this problem is worth that level of intrusion for most programmers.  But a 
> soft enforcement, maybe an opt-in one like the Clang static analyzer, could 
> do a lot to prod people in the right direction.

Sure, I'm worried about the fact that because POSIX is a piece of cr^W^W^W^Wso 
beautifully designed, if you unlock a mutex from another thread that the one 
locking it, you're not allowed to crash to tell the client he made a 
programming mistake.

the unfair lock on Darwin will abort if you try to do something like that 
though.

We'll see how much users will make these mistakes I guess.

-Pierre
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to