Std::process::id() vs libc::pid_t - how to handle?


I just discovered that std::process::id() returns a u32, but libc::pid_t is defined as i32.
I need to pass a libc::pid_t to the systemd crate (systemd::daemon::pid_notify), I am not working with libc directly.

How to handle this?

One solution would be to use libc::getid, but that would mean that I had to use unsafe in my codebase, which I do not want to have. Casting is not a solution, is it?

You can check the bounds and cast.

Sure, but what happens if we have an out of bounds? I mean... does this happen? Does it mean I cannot pass the PID to the function (or any function using a libc::pid_t) just because the PID is out of range of the type, even though if semantically that would succeed?

Sounds like a real issue to me if I cannot use an interface just because a PID is too high?

It cannot exceed. The libc crate's type reflects the actual underlying OS's representation of PID's. It doesn't exceed in the actual OS, hence it cannot actually overflow.
On the other hand, the stdlib's PID representation has to encompass different OS's. So either there is some OS that requires a full u32 for a PID or they were playing safe.
At any rate, you can actually blindly cast, but I suggested putting a check to be safe.
Also, the libc type has to be i32 since pid_t must accomodate negative "PID's", which often represent a process group (I believe kill has this semantic). But this negative PID is just the PID of the process group leader with a negative sign - which implies that all actual PID's must have 0 in the MSB.

1 Like

You can either blindly as-cast, or use .try_into().unwrap() for a runtime error on out of range values.