all OS functions should be "nothrow @trusted @nogc"

Moritz Maxeiner via Digitalmars-d digitalmars-d at puremagic.com
Wed Jul 26 02:06:19 PDT 2017


On Wednesday, 26 July 2017 at 06:44:51 UTC, Shachar Shemesh wrote:
> On 25/07/17 18:29, Moritz Maxeiner wrote:
>> On Tuesday, 25 July 2017 at 14:39:15 UTC, Shachar Shemesh 
>> wrote:
>>> On 25/07/17 17:24, Moritz Maxeiner wrote:
>>>> On Tuesday, 25 July 2017 at 13:50:16 UTC, Shachar Shemesh 
>>>> wrote:
>>>>> The title really does says it all.
>>>>
>>>> Since you explicitly state *all* OS functions:
>>>> nothrow: Should be OK (only callbacks could violate this and 
>>>> they should be nothrow, anyway).
>>> Technically, any system call that is a pthreads cancellation 
>>> point may throw a C++ exception.
>> 
>> Good to know, then since D is supposed to be able to catch C++ 
>> exceptions (and can on 64bit Linux [1]) none of those may be 
>> attributed as `nothrow`, because C++ exceptions don't derive 
>> from `Error` >
>>>
>>> If we go down that route, however, calling system calls from 
>>> nothrow becomes completely impossible, which is another way 
>>> of saying that decorating just about anything with nothrow 
>>> becomes impossible.
>> 
>> No. `nothrow` functions can call throwing ones, as long as 
>> they catch any exceptions not derived from Error thrown by 
>> them.
>> 
>
> And right there and then you've introduced a serious problem.
> The purpose of the C++ exception thrown on cancellation point 
> is to terminate the thread. It is designed to be uncatchable.

The issue lies with the definition of `nothrow` considering only 
D Throwables;
it would have to be updated to apply to C++ exceptions that 
equate to D exceptions derived from Error.

>
> I think labeling these "nothrow" is the correct course of 
> action.

Not with the `nothrow` spec as it is right now. After the spec 
having been updated to apply to C++ exception that may not be 
caught, sure.

>>> I'm not sure this is the most compelling argument, however. 
>>> The function passed to pthread_create does not, logically, 
>>> run in the pthread_create function. As such, I don't think 
>>> this logic holds.
>> 
>> Then the @nogc definition would need to be updated from: "or 
>> indirectly through functions it may call" to reflect this, 
>> because that can be interpreted both ways.
>> 
>>>
>>> As for pthread_join, I have no idea what you meant by it. 
>>> Please elaborate why you think it is a problem.
>> 
>> Possible scenario on single core (no hyperthreading) system:
>> - thread 1 spawns thread 2
>> - thread 1 enters @nogc function `foo` and calls 
>> `pthread_join` on thread 2 before its own timeslice is over 
>> (and thus enters blocked state)
>> - thread 2 does work allocating via the GC, then terminates
>> - thread 1 wakes up and leaves @nogc function `foo`
>> 
>> Because @nogc (in contrast to nothrow) is explicitly designed 
>> as transitive, logically speaking, `foo` violated its @nogc 
>> constraint (it *caused* the GC allocations in thread 2).
>
> Following that logic, ANY function that might affect another 
> thread cannot be @nogc.

Not any function; as I interpret the spec only those who manually 
interleave another thread allocating via the GC such that it 
looks to a caller as if they had allocated using the GC.

> I think this way madness lies. I don't think other threads 
> action, even if linked in some weird semantic way to ours, make 
> us accountable to their actions.

I would say it depends on the exact semantics of each use case 
whether we are accountable.

>
> If you pass a callback that is not @nogc to pthread_create, 
> then your other thread might allocate. This doesn't change the 
> fact that pthread_create doesn't allocate.

The "indirectly through functions it may call" of the @nogc spec 
is ambiguous here because it doesn't actually require a direct 
call chain to the allocation. It would need to be updated.

> At Weka, we use this understanding of the semantics all the 
> time. Our main thread is as @nogc as we can possibly make it. 
> Whenever we need anything that violates our usual restrictions, 
> we send it either to other threads or other processes for 
> execution, and use the results when they return. Defining the 
> various attributes too strictly will simply mean we cannot use 
> them anywhere (which is pretty much what happens today, but the 
> very thing I'm trying to change here).

There is a difference between what's sensible and what the 
current wording of the spec allows for and before it's OK to 
attribute functions where the ambiguity applies, the spec wording 
(for both @nogc and nothrow) has to be made unambiguous.

P.S.: In case it's not clear: I'm playing devil's advocate in 
this subthread.


More information about the Digitalmars-d mailing list