libc icon indicating copy to clipboard operation
libc copied to clipboard

libc::clone() should take an unsafe callback

Open jstarks opened this issue 4 years ago • 10 comments

On Linux, clone takes a callback function pointer. The function pointer type is not marked unsafe, but there is basically no way to implement this callback with a safe function since it takes its context parameter by pointer.

It seems to me that unsafe should be added to the function pointer type, e.g.:

    pub fn clone(
        cb: unsafe extern "C" fn(*mut ::c_void) -> ::c_int,
        child_stack: *mut ::c_void,
        flags: ::c_int,
        arg: *mut ::c_void,
        ...
    ) -> ::c_int;

I'm not certain, but I don't think this would be a breaking change.

jstarks avatar May 26 '21 16:05 jstarks

I'm not sure why this change is needed as that function should be usable currently. For instance, it's normally used on the user codebase: https://github.com/nix-rust/nix/blob/b4d4b3183b75addf7cad83c57994a62a89235ed4/src/sched.rs#L194-L201

I'm not certain, but I don't think this would be a breaking change.

Yup, it'll be a breaking change.

JohnTitor avatar Jun 01 '21 15:06 JohnTitor

Sure, it's possible to work around this via transmute. It just introduces another opportunity for error.

I guess this is a breaking change because someone might care about the type of the clone function, is that right? As long as clone is not used as a function pointer, then this change would not cause any existing program to fail to compile, no?

jstarks avatar Jun 01 '21 16:06 jstarks

If it's usable then I don't see any strong reason to change. Could you show some situation it should be changed?

JohnTitor avatar Jun 01 '21 16:06 JohnTitor

We can agree it's a bug, right? Just one that can be worked around. I defer to your judgment whether it's worth fixing; feel free to close.

jstarks avatar Jun 01 '21 16:06 jstarks

I don't think it's a bug but an improvement, though. So, adding unsafe helps some usage (and it doesn't break any build), I'm happy to accept that change. Therefore I'd like to see an example you consider.

JohnTitor avatar Jun 01 '21 16:06 JohnTitor

Yup, it'll be a breaking change.

is not libc still 0.x.y, which means it can have breaking changes?

pro465 avatar Nov 05 '21 07:11 pro465

You don't have to use the context parameter.

joshtriplett avatar Nov 16 '21 15:11 joshtriplett

@JohnTitor

I'm not certain, but I don't think this would be a breaking change.

Yup, it'll be a breaking change.

how? are not safe fn pointers implicitly castable to unsafe fn pointers?

link to working example with the same typed fn pointer as the OP's suggestion:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=use%20std%3A%3Affi%3A%3Ac_void%3B%0Ause%20std%3A%3Aos%3A%3Araw%3A%3Ac_int%3B%0A%0Aextern%20%22C%22%20fn%20foo(%3A%20*mut%20c_void)%20-%3E%20c_int%20%7B%201%20%7D%0A%0Afn%20takes_unsafe_callback(callback%3A%20unsafe%20extern%20%22C%22%20fn(*mut%20c_void)%20-%3E%20c_int)%20%7B%0A%20%20%20%20unsafe%20%7B%20callback(0%20as%20)%3B%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20takes_unsafe_callback(foo%20as%20extern%20%22C%22%20fn(*mut%20c_void)%20-%3E%20c_int)%3B%0A%7D

pro465 avatar Nov 19 '21 16:11 pro465

Let's just do this for 1.0, along with any other functions that take a callback with pointer arguments. PRs are welcome!

tgross35 avatar Aug 29 '24 05:08 tgross35

Just for context, the problem is that Rust's best practices require all safe (even internal) functions to be sound when called with arbitrary arguments. However, a callback that doesn't just ignore its argument but casts it to *const UserData and then dereferences the pointer cannot be sound for arbitrary arguments, that is, be safe. So following safety-oriented best practices (marking the callback unsafe fn) requires jumping through extra unsafe hoops (transmuting the callback from unsafe fn to fn at the invocation of clone), which in practice leads to the best practices (if you can even call them that, they are more akin to strict rules) not being followed at all.

I'm glad this is going to be fixed in 1.0.

purplesyringa avatar Sep 05 '24 16:09 purplesyringa