5

I'm trying to call the reboot function from libc in Python via ctypes and I just can not get it to work. I've been referencing the man 2 reboot page (http://linux.die.net/man/2/reboot). My kernel version is 2.6.35.

Below is the console log from the interactive Python prompt where I'm trying to get my machine to reboot- what am I doing wrong?

Why isn't ctypes.get_errno() working?

>>> from ctypes import CDLL, get_errno
>>> libc = CDLL('libc.so.6')
>>> libc.reboot(0xfee1dead, 537993216, 0x1234567, 0)
-1
>>> get_errno()
0
>>> libc.reboot(0xfee1dead, 537993216, 0x1234567)
-1
>>> get_errno()
0
>>> from ctypes import c_uint32
>>> libc.reboot(c_uint32(0xfee1dead), c_uint32(672274793), c_uint32(0x1234567), c_uint32(0))
-1
>>> get_errno()
0
>>> libc.reboot(c_uint32(0xfee1dead), c_uint32(672274793), c_uint32(0x1234567))
-1
>>> get_errno()
0
>>>

Edit:

Via Nemos reminder- I can get get_errno to return 22 (invalid argument). Not a surprise. How should I be calling reboot()? I'm clearly not passing arguments the function expects. =)

Community
  • 1
  • 1
tMC
  • 18,105
  • 14
  • 62
  • 98

2 Answers2

4

Try:

>>> libc = CDLL('libc.so.6', use_errno=True)

That should allow get_errno() to work.

[update]

Also, the last argument is a void *. If this is a 64-bit system, then the integer 0 is not a valid repesentation for NULL. I would try None or maybe c_void_p(None). (Not sure how that could matter in this context, though.)

[update 2]

Apparently reboot(0x1234567) does the trick (see comments).

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • trying `libc.reboot(0xfee1dead, 672274793, 0x1234567, c_void_p(None))` still returns errno 22. thanks for the idea though. (so does trying to use `c_uint()` around the args) – tMC Jun 01 '11 at 03:11
  • Have you tried just `reboot(0x1234567)`? That's the signature I see in sys/reboot.h... – Nemo Jun 01 '11 at 03:19
  • I thought I had, but I guess not- that seems to do the trick. Maybe update the answer? – tMC Jun 01 '11 at 03:41
3

The reboot() in libc is a wrapper around the syscall, which only takes the cmd argument. So try:

libc.reboot(0x1234567)

Note that you should normally be initiating a reboot by sending SIGINT to PID 1 - telling the kernel to reboot will not give any system daemons the chance to shut down cleanly, and won't even sync the filesystem cache to disk.

caf
  • 233,326
  • 40
  • 323
  • 462