#include "stdio.h" #include "string.h" #include "unistd.h" #ifndef __GNUC__ # error requires the GNU compiler #endif extern const char* __progname; /* call printf() only if inside python binary */ static void _printf (const char* fmt, const char* arg1, const char* arg2) { if (!strcmp("python", __progname)) { if (printf(fmt, arg1, arg2) < 0) { _exit(9); /* stdout closed? */ } } } #if 0 /* pick this ... */ static void __attribute__((constructor)) /* called on main() */ _ctor (void) { _printf("*** %s called in %s ...\n", "ctor", __progname); } static void __attribute__((destructor)) /* called on exit() */ _dtor (void) { _printf("*** %s called in %s ...\n", "dtor", __progname); } #else /* ... or this case */ static void /* called on Python exit */ _dtor (void) { _printf("*** %s called in %s ...\n", "dtor", __progname); } /* the weak attribute prevents unresolved symbol errors */ extern int Py_AtExit (void(*func)(void)) __attribute__((weak)); static void __attribute__((constructor)) /* called on main() */ _ctor (void) { _printf("*** %s called in %s ...\n", "ctor", __progname); if (Py_AtExit) { _printf("*** %s %s\n", "Py_AtExit", (Py_AtExit(_dtor) < 0 ? "failed!" : "OK")); } } #endif /* ===================================================== Build this file into a shared library, then pre-load that library with the Python binary as follows. On Linux, compile as gcc -o dlibtest.os -c -m32 -Wall -Werror -fPIC dlibtest.c gcc -o dlibtest.so -m32 -ldl -shared dlibtest.os and then run env LD_PRELOAD=./dlibtest.so .../python On MacOS X, compile as gcc -o dlibtest.os -c -Wall -Werror -march=i686 -fPIC dlibtest.c gcc -o dlibtest.dylib -undefined dynamic_lookup -lpthread -dynamiclib dlibtest.os and run env DYLD_INSERT_LIBRARIES=./dlibtest.dylib .../python.exe To preload the library within gdb (on Linux) use gdb .../python (gdb) set environment LD_PRELOAD ./dlibtest.so (gdb) run ..... or use setenv LD_PRELOAD ./dlibtest.so gdb .../python (gdb) run ..... After Ctrl-D two messages should have been printed, but 3.0a1 prints only the first one. An exist status is 9 or 011 indicates that a printf error occurred. Here is a log from Linux with my 3.0a1 and 2.51 builds and with 2.3.4 included with the Linux distro: $ gcc -o dlibtest.os -c -m32 -Wall -Werror -fPIC dlibtest.c $ gcc -o dlibtest.so -m32 -ldl -shared dlibtest.os $ env LD_PRELOAD=./dlibtest.so ~/Python-3.0a1/python *** ctor called ... Python 3.0a1 (py3k, Oct 26 2007, 09:45:17) [GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> $ env LD_PRELOAD=./dlibtest.so ~/Python-2.5.1/python *** ctor called ... Python 2.5.1 (r251:54863, Oct 22 2007, 16:19:11) [GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> *** dtor called ... $ env LD_PRELOAD=./dlibtest.so /usr/bin/python *** ctor called ... Python 2.3.4 (#1, May 2 2007, 19:26:00) [GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> *** dtor called ... Similarly on MacOS X with Python 2.3.5 distributed by Apple: % env DYLD_INSERT_LIBRARIES=./dlibtest.dylib ~/Python-3.0a1/python.exe *** ctor called ... Python 3.0a1 (py3k, Oct 25 2007, 14:55:57) [GCC 4.0.1 (Apple Computer, Inc. build 5367)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> ^D % env DYLD_INSERT_LIBRARIES=./dlibtest.dylib ~/Python-2.5.1/python.exe *** ctor called ... Python 2.5.1 (r251:54863, Oct 22 2007, 16:18:08) [GCC 4.0.1 (Apple Computer, Inc. build 5341)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> ^D *** dtor called ... % env DYLD_INSERT_LIBRARIES=./dlibtest.dylib /usr/bin/python *** ctor called ... Python 2.3.5 (#1, Jan 13 2006, 20:13:11) [GCC 4.0.1 (Apple Computer, Inc. build 5250)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> ^D *** dtor called ... /Jean Brouwers PS) For more details on the con/destructor attributes, see the GNU gcc documentation at See also Apple's documentation DynamicLibrary.pdf which contains some excellent examples plus special MacOS X features. E.g. c/dtor must be ZPRIVATE and a static ctor can have main-like argc, argv and envp arguments! ===================================================== */