I am attempting to implement a C extension in Python. The extension works, but as soon as the module is imported, errno
is set to ENOENT
(2).
simple.c
#include <Python.h>
#include <errno.h>
static PyMethodDef KeypadMethods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC initkeypadinterface(void)
{
PyObject* m;
int stat;
stat = errno;
if (stat)
{
printf("There was an error: %d\n", stat);
}
m = Py_InitModule3("keypadinterface", KeypadMethods, "Interface to the keypad driver");
if (m == NULL)
{
return;
}
}
setup.py
from distutils.core import setup, Extension
module1 = Extension('keypadinterface',
sources = ['simple.c'])
setup (name = 'KeypadInterface',
version = '0.1',
description = 'Provides a python interface to the keypad driver',
ext_modules = [module1])
python setup.py build
output:
running build
running build_ext
building 'keypadinterface' extension
creating build
creating build/temp.linux-x86_64-2.7
x86_64-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c simple.c -o build/temp.linux-x86_64-2.7/simple.o
creating build/lib.linux-x86_64-2.7
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security build/temp.linux-x86_64-2.7/simple.o -o build/lib.linux-x86_64-2.7/keypadinterface.so
Using gdb with a watch on errno results in this traceback:
(gdb) c
Continuing.
Hardware watchpoint 1: errno
Old value = 0
New value = 2
0x00007f9974e271d0 in __xstat64 () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0 0x00007f9974e271d0 in __xstat64 () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00000000004d4ea6 in stat (__path=<optimized out>, __statbuf=<optimized out>)
at /usr/include/x86_64-linux-gnu/sys/stat.h:455
#2 isdir (path=0x14bf430 "keypadinterface") at ../Python/import.c:133
#3 find_module.38998 (fullname=fullname@entry=0x14be420 "keypadinterface", subname=<optimized out>,
subname@entry=0x14be420 "keypadinterface",
path=['', '/usr/local/lib/python2.7/dist-packages/esptool-0.1.0-py2.7.egg', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PILcompat', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client'], path@entry=0x0, buf=<optimized out>, buf@entry=0x14bf430 "keypadinterface",
buflen=buflen@entry=4097, p_fp=p_fp@entry=0x7fff1d45bb80, p_loader=p_loader@entry=0x7fff1d45bb70)
at ../Python/import.c:1497
#4 0x0000000000540922 in import_submodule.39248 (mod=mod@entry=None,
subname=subname@entry=0x14be420 "keypadinterface", fullname=0x14be420 "keypadinterface")
at ../Python/import.c:2689
#5 0x0000000000540d08 in load_next (mod=None, altmod=None, p_name=p_name@entry=0x7fff1d45bc78,
buf=buf@entry=0x14be420 "keypadinterface", p_buflen=p_buflen@entry=0x7fff1d45bc80)
at ../Python/import.c:2515
#6 0x000000000054111b in import_module_level.isra.3.39267 (name=0x0,
name@entry=0x7f99753d4d74 "keypadinterface",
globals=globals@entry={'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, fromlist=fromlist@entry=None, level=level@entry=-1) at ../Python/import.c:2224
#7 0x000000000051dc50 in PyImport_ImportModuleLevel (level=-1, fromlist=None, locals=<optimized out>,
globals={'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, name=0x7f99753d4d74 "keypadinterface") at ../Python/import.c:2288
#8 builtin___import__ (self=<optimized out>, args=<optimized out>, kwds=<optimized out>)
at ../Python/bltinmodule.c:49
#9 0x00000000004dc9cb in PyObject_Call (kw=0x0,
arg=('keypadinterface', {'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, {...}, None), func=<built-in function __import__>)
at ../Objects/abstract.c:2529
#10 PyEval_CallObjectWithKeywords (func=func@entry=<built-in function __import__>,
arg=arg@entry=('keypadinterface', {'__builtins__': <module at remote 0x7f99754dbb08>, '__name__': '__main__', '__doc__': None, '__package__': None}, {...}, None), kw=kw@entry=0x0) at ../Python/ceval.c:3889
#11 0x000000000049b87e in PyEval_EvalFrameEx (
f=f@entry=Frame 0x7f9975504c20, for file <stdin>, line 1, in <module> (), throwflag=throwflag@entry=0)
at ../Python/ceval.c:2333
#12 0x00000000004a1634 in PyEval_EvalCodeEx (closure=0x0, defcount=0, defs=0x0, kwcount=0, kws=0x0,
argcount=0, args=0x0, locals=<optimized out>, globals=<optimized out>, co=0x7f9975415b30)
at ../Python/ceval.c:3252
#13 PyEval_EvalCode (locals=<optimized out>, globals=<optimized out>, co=0x7f9975415b30)
at ../Python/ceval.c:667
#14 run_mod.42576 (mod=mod@entry=0x14bc470, filename=filename@entry=0x60e5bd "<stdin>",
globals=<optimized out>, locals=<optimized out>, flags=flags@entry=0x7fff1d45c0b0,
arena=arena@entry=0x1444780) at ../Python/pythonrun.c:1370
#15 0x000000000044e87c in PyRun_InteractiveOneFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>,
filename=filename@entry=0x60e5bd "<stdin>", flags=flags@entry=0x7fff1d45c0b0) at ../Python/pythonrun.c:857
#16 0x000000000044e998 in PyRun_InteractiveLoopFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>,
filename=filename@entry=0x60e5bd "<stdin>", flags=flags@entry=0x7fff1d45c0b0) at ../Python/pythonrun.c:777
#17 0x000000000044ed70 in PyRun_AnyFileExFlags (fp=fp@entry=0x7f99750fb640 <_IO_2_1_stdin_>,
filename=filename@entry=0x60e5bd "<stdin>", closeit=closeit@entry=0, flags=flags@entry=0x7fff1d45c0b0)
at ../Python/pythonrun.c:746
---Type <return> to continue, or q <return> to quit---
#18 0x000000000044f904 in Py_Main (argc=<optimized out>, argv=0x7fff1d45c268) at ../Modules/main.c:640
#19 0x00007f9974d5dec5 in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#20 0x0000000000578c4e in _start ()
(gdb)
I read that stat functions can set errno
to ENOENT
when a component of the path being stat
'ed doesn't exist. But the module still works so the path must be correct, right?
There must be something incredibly stupid that I have done, but I have yet to find it.
In case it matters: Python 2.7.6 on Linux Mint 17.1 with GCC 4.8.4
A lot of code sets errno
pre-emptively before performing an operation since multiple code paths may result in the same error being returned. For this reason the value in errno
should be ignored unless the code explicitly returns an error result.