-
Notifications
You must be signed in to change notification settings - Fork 666
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add reboot() support on Linux #386
Conversation
To test, as root: extern crate nix;
use nix::sys::reboot::*;
fn main() {
println!("Restarting");
reboot(RebootMode::Restart).unwrap();
unreachable!();
} |
Thank you for the pull request. My understanding is, that we aim with nix to provide rust-style wrappers for rust-libc. So, I would prefer, if you could get all necessary ffi-bindings and constants into libc first. This has the advantage that libc has test infrastructure that ensures that bindings and constants exist and use the correct type. In addition, we put our code in files with names corresponding to their C includes. According to http://man7.org/linux/man-pages/man2/reboot.2.html, your code should be in In general, you should have look at the CONVENTIONS.md file. |
|
First of all, sorry about the Regarding your third point: If something from a libc-header or |
Filed rust-lang/libc#333 |
So that got merged, now waiting for either #387 (or its analogue) to be accepted -- or a libc release. |
Ok, #387 merged, so things should be ready for a refresh. |
Force using the constants even on x86 where they do not fit into isize (c_int)
Great! Should I merge or rebase? |
"Timed out waiting for reply" 😄 |
OK, so:
Also, I went with |
So |
use void::Void; | ||
use std::mem::drop; | ||
|
||
#[derive(Copy, Clone, Debug, Eq, PartialEq)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you switch Clone and Copy? (I know it's pedantic, I'll provide more substantial feedback momentarily)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. Is there a general convention about the preferred order of stuff in #derive
? If so, maybe it should be mentioned/documented somewhere?
I commented on your changes. If the comments are addressed - through discussion or commits - I would like to merge this pull request. Thank you for the work. |
Please feel free to merge this if you think I've addressed your comments -- and thanks for the review. |
/// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for | ||
/// enabling/disabling Ctrl-Alt-Delete. | ||
#[derive(Clone, Copy, Debug, Eq, PartialEq)] | ||
pub enum RebootMode { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Somehow a comment went missing yesterday; I might have forgotten to press comment).
What problem did occur when you tried to use #[repr(i32)]
? All constants have type libc::c_int
which is an alias for i32
. The enumeration Signal
in sys/signal.rs
does the same. You could then get rid of the match bellow.
As you can see there, I used the name of the corresponding constants for the elements of the enumeration. I would prefere if we did that here as well, even though we have no convention yet. However, bitflags types use this convention, so it would be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having looked at your commit history, your problem probably was that you still have to cast the enumeration elements to libc::c_int
in order to pass them to reboot
, i.e.
reboot(cmd as libc::c_int)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you can see from this commit, that's exactly what I tried before, and here's the Travis failure that GitHub UI displays as a little red cross next to the commit -- however now that I look carefully I see that the commit hash is wrong and the link back gives me 404 -- is it a bug or something (I definetely commited that after rebasing)?
On your "middle" point -- do you mean to call the enum variants RebootMode::RB_POWER_OFF
as so on? Doesn't seem beautiful; but if that's the convention -- OK ¯\_(ツ)_/¯
. I would rather prefer to name them appropriately and list the C analogues in the documentation, but we obviously can't rename all of the bitflags now, so consistency wins, yeah.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding the names, you understood me correctly.
I had a look at the Travis output and I dont understand it. The constants are libc::c_int
in libc, which is i32
hence an enumeration with #[repr(i32)] should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So maybe it is a bug in GH/Travis. Let me change the names and try #[repr(i32)]
one more time then.
It's failing again... |
I'll have time to investigate this behavior on the weekend. If you're in
a hurry, you have to look into it yourself. I just want to understand,
why we can not go this route, if we really can not.
|
No, I'm unlikely to need this sooner than in a week, if ever. I'd really appreciate any help with investigating this, because I don't see any pattern in the failures -- they happen across different architectures and compiler versions, while other builds in seemingly similar conditions pass. |
I can help take a look as well as I will be wanting |
Dumb me -- there obviously is a pattern. Ignoring Mac builds as they don't compile the module, failures happen on -- and only on -- rusc versions older than "stable". Maybe there was a bug that got fixed? |
I looked into it. We can get rid of the error (and rid of similar warning in libc stable and younger) by declaring the constant literals to be
I'll prepare a patch for libc. |
Yeah, but the questions are:
|
Yes-and-no. They fit when you interpret them as C does (if you printed the number with the cast to i32 you have a negative number).
This is a system call. There aren't really real types associated at that point in time (the value could be a value, pointer, etc.). Way back in the day, libc probably should have defined the interface explicitly as u32 but they didn't. For C where the constants are defined using
I'm still wondering about that as well. @alexcrichton Any ideas? |
We've had a number of changes to the constant folder and such recently, mostly in the area of fixing bugs but perhaps a few accidental corner cases were fixed only later? Other than that I'm also not sure what's happening :( |
Not that this is all really important, but I'm just trying to better understand what's going on, so anyway:
True, the value is "untyped" between libc and the syscall handler, but it's "typed" on both sides -- and I see no reason for the types to differ. I peeked into the kernel source and guess what -- it's indeed
I see it was added on 23 May 1996 (according to this), but all the mailing list archives I can find only go back to 1999 😢
It's strange that the C compiler (at least gcc) doesn't warn you that the value overflows -- because it does so when you pass something really big, like
It shouldn't matter whether the conversion from "the constant" to the actual type is performed -- at the definition or when passing arguments to the function -- either the value fits into Anyway, since rust-lang/libc#334 is merged (btw how come we didn't get the same warning/error there before?), this should be good to go now? |
If building this fine (as opposed to failing with an error) on newer versions is a bug, then it's still not fixed -- the current nightly builds this fine (just checked).
By any chance, are you working on something interesting [that you are allowed to talk about]? Am I wrong in assuming that |
The behavior in stable and newer versions is perfectly fine. You get a warning when declaring the constants. After that the constant has type I restarted the CI. |
Did it give a warning when the constants were added to libc? I don't remember getting one. |
They might have disabled it. I did get a warning, in my test app. |
@homu r+ |
📌 Commit 215f387 has been approved by |
⚡ Test exempted - status |
Add reboot() support on Linux This adds support for calling [reboot(2)](http://linux.die.net/man/2/reboot) on Linux (useful for implementing PID 1!). * **Testing**: I can't imagine how this could be tested other than manually, which is what I did to ensure it works. * **libc**: for some reason libc includes neither `reboot()` function, nor `RB_*` constants, so I had to hack-define them here. Should I open a bug/PR against the libc crate? * **API**: I went with `reboot()` function for restarting, powering off, halting, etc. and an additional `set_cad_enabled()` function for enabling/disabling Ctrl-Alt-Delete, which still corresponds to `reboot()` C call, but has different semantics and return type. (But I'm open to suggestions here -- maybe it would be better to separate each action into its own function, i.e. `restart()`, `poweroff()`, `halt()`?) * **Documentation**: I see most of the things in nix are undocumented, so I didn't document anything except for the `set_cad_enabled()` function, which obviously uses a non-standard name. * **Portability**: I implemented the Linux version as I'm not familiar with anything else, but there surely are others (ex. [BSD](http://www.freebsd.org/cgi/man.cgi?reboot(2))). If I didn't mess up anything, the new code is only compiled on Linux/Android, so it should be straightforward to implement the other versions too.
Thank you for going through the (rather long) process bugaevc. |
Great! Thank you for helping me get it done. |
Nothing terribly interesting. I work in embedded systems and have seen cases where a poorly behaving process/init script can block the system from rebooting when going through init. Calling boot directly is something I might do in logic after a long delay to ensure that the system does reboot. There aren't any humans around to hold down the power button... |
This adds support for calling reboot(2) on Linux (useful for implementing PID 1!).
reboot()
function, norRB_*
constants, so I had to hack-define them here. Should I open a bug/PR against the libc crate?reboot()
function for restarting, powering off, halting, etc. and an additionalset_cad_enabled()
function for enabling/disabling Ctrl-Alt-Delete, which still corresponds toreboot()
C call, but has different semantics and return type. (But I'm open to suggestions here -- maybe it would be better to separate each action into its own function, i.e.restart()
,poweroff()
,halt()
?)set_cad_enabled()
function, which obviously uses a non-standard name.