d-unsed / ruru

Native Ruby extensions written in Rust
MIT License
832 stars 40 forks source link

C Namespace collisions #70

Closed tinco closed 6 years ago

tinco commented 7 years ago

If you define a method called "gets" the code will compile, but will segfault whenever the method is called because the binding will collide with libc's gets, the latter overriding the former.

It happened to me, and it took me an hour or two before realizing what was going on.

So I had code like this:

class!(InputStream);
methods!(InputStream, itself,
     fn gets() -> AnyObject {
        NilClass::new().to_any_object()
     }
)
#[no_mangle]
pub extern fn init() {
    Class::new("InputStream", None).define(|itself| {
                itself.def("gets", gets);
    }
}

When I discovered what was going on (by using GDB to get backtraces) the workaround was clear, renaming gets to InputStream_gets did the trick. I did not see mention of this in the docs, so one solution could be to just add a warning to the docs. A more robust solution would be to prefix the C function names automatically, maybe with something like __ruru_.

d-unsed commented 7 years ago

Hey @tinco!

Probably the problem is that the functions created by methods! macro are marked as no_mangle. This is not necessary, so the fix should be pretty easy, just by removing no_mangle. I will double check if this is true and let you know

danielpclark commented 7 years ago

I've found the naming scheme for methods in the methods! macro is very particular; although it may not be responsible for the issue. When I created a method named basename and called a function in a module of the same name basename::basename I would get segfaults in the execution of the code from calls from Ruby. So I preceded all my ruru methods with r_ and that fixed everything.

d-unsed commented 6 years ago

This issue should be resolved with 4524787de9d230b0fc3f5fd18427067640dbff56 and the fix will be released in 0.10.0

tinco commented 6 years ago

Thanks!