SiegeLord / DAllegro5

D binding to the Allegro5 game development library
Other
42 stars 15 forks source link

Extern(C) functions should be `nothrow @nogc` #36

Closed mleise closed 7 years ago

mleise commented 7 years ago

If they don't call D code internally, C functions should be marked extern(C) nothrow @nogc { … }.

rcorre commented 7 years ago

call D code internally

Would this include any C function that takes a function pointer, as it could be passed a D function (marked with extern(C)) that allocates or throws?

rikkimax commented 7 years ago

@rcorre you can mark functions/delegates as nothrow.

alias myFunc = extern(C) void function() nothrow;

Any function being passed to or is a c function declaration should really be nothrow @system @nogc. After all c code won't be calling our GC, throwing our exceptions and is most definitely not safe.

rcorre commented 7 years ago

So marking a such a C function as @nogc nothrow would prevent passing any function that isn't also @nogc nothrow, which is generally a 'good thing'? Would the passed function have to be explicitly marked as such or can it be implied (i.e. could it break existing code)?

rikkimax commented 7 years ago

There are two separate cases going on here:

1)

extern(C)
void cFunc() nothrow @system @nogc;

2)

alias ACFunc = extern(C) void function() nothrow @system @nogc;

extern(C)
void cFunc(ACFunc arg)  nothrow @system @nogc;

So in the first case is the same as defining a function in C and exporting it for access via shared library loading, but it won't accept any arguments that are functions.

In the second case we pass in a function to a C function. Keep in mind both the C function as well as the argument must be declared as being extern(C) as well as nothrow @system @nogc.

After all, our exceptions and GC collecting won't work from within C code and good chance it'll end in a segfault.

The only attribute that can be not included in this is @nogc as long as you know what the C code is doing and in most cases its fine.

mleise commented 7 years ago

I've experienced such segfaults first hand some time ago with GtkD. My D code threw an exception inside C code and druntime tried to unwind the stack. To do so it looks at the frame pointer register, but all my C libraries are compiled without explicit frame pointer. So druntime misinterpreted the register for a stack frame and crashed when dereferencing it. This request here doesn't have to do with that though. I'd just like to use Allegro5 in code marked @nogc and thought I should put a "reminder" somewhere.