Jean Brouwers added the comment:

I could not try Neal's patch since it does not seem to apply to the 
3.0a1 source I have.  But the Modules/_fileio.c patch works just fine on 
my Linux and MacOS X.  Here is the Linux result: 

$ env  LD_PRELOAD=./dlibtest4.so  ~/Python-3dbg/python
*** ctor called in python ...
*** atexit OK in python ...
Python 3.0a1 (py3k, Oct 28 2007, 10:23:59) 
[GCC 3.4.6 20060404 (Red Hat 3.4.6-8)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
[36000 refs]
[21985 refs]
*** dtor called in python ...
$

Most interesting is that this Python build --with-pydebug now prints 2 
lines in [..] brackets on exit.  That 2nd line, [21985 refs] never 
showed up before!

Also, attached is another version of my test case renamed to dlibtest4.  
It includes 4 different use cases.  More details inside.

Added file: http://bugs.python.org/file8645/dlibtest4.c

__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1329>
__________________________________
#define _USECASE  2

/* =====================================================

Pick an exit handling case by setting the _USECASE value
above.  The 4 choices are

 1 - using function __attribute__((destructor))

 2 - using stdlib function atexit

 3 - using Py_AtExit looked up with dlsym

 4 - using Py_AtExit and __attribute__((weak)) 


Build this file into a shared library.  On Linux use

 gcc -o dlibtest4.os -m32 -Wall -Werror -fPIC -c dlibtest4.c
 gcc -o dlibtest4.so -m32 -ldl -shared dlibtest4.os

or MacOS X with

 gcc -o dlibtest4.os -Wall -Werror -march=i686 -c -fPIC dlibtest4.c
 gcc -o dlibtest4.dylib -undefined dynamic_lookup -dynamiclib dlibtest4.os


Then pre-load that library with the Python binary on Linux

 env LD_PRELOAD=./dlibtest4.so  .../python

an on MacOS X

 env DYLD_INSERT_LIBRARIES=./dlibtest4.dylib  .../python.exe


Type Ctrl-D or exit() to quit python.

In total, three messages should have been printed.  But 3.0a1
prints only the first two

 *** ctor called in python...
 *** <varies>

and never the last one

 *** dtor called in python...

An exit status is 9 or 011 indicates that a printf error
occurred on exit.


/Jean Brouwers  <[EMAIL PROTECTED]>


PS) To preload the library within gdb (on Linux) use

   gdb  .../python
   (gdb) set environment LD_PRELOAD ./dlibtest4.so
   (gdb) run
   .....

or use

   setenv LD_PRELOAD ./dlibtest4.so
   gdb .../python
   (gdb) run
   .....


PPS) For more details on the con/destructor attributes, see the GNU
gcc documentation at

 <http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Attributes.html>

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!

   ===================================================== */

#ifndef __GNUC__
# error requires the GNU compiler
#endif

#include "stdio.h"
#include "string.h"
#include "unistd.h"

extern const char* __progname;

/* call printf() only if inside python[.exe] binary */
static void
_print2 (const char* a1, const char* a2)
{
    if (!strncmp("python", __progname, 6)) {
        if (printf("*** %s %s in %s ...\n", a1, a2, __progname) < 0) {
            /* printf failed, try perror but
               that message does not show up
               on 3.0a1 either */
            perror("stdout closed?");
            /* last resort */
            _exit(9);  /* note, _exit! */
        }
    }
}


#if _USECASE == 1  /* con-/destructor functions */

static void  __attribute__((constructor))  /* called on main() */
_ctor (void)
{
    _print2("ctor", "called");
    _print2("using", "__attribute__");
}

static void __attribute__((destructor))  /* called on exit() */
_dtor (void)
{
    _print2("dtor", "called");
}


#elif _USECASE == 2  /* atexit */

#include <stdlib.h>

static void
_dtor (void)
{
    _print2("dtor", "called");
}

static void  __attribute__((constructor))
_ctor (void)
{
    _print2("ctor", "called");
    _print2("atexit", (atexit(_dtor) ? "failed!" : "OK"));
}


#elif _USECASE == 3  /* dlsym Py_AtExit */

#define __USE_GNU  /* for RTLD_DEFAULT */
#include <dlfcn.h>

static void
_dtor (void)
{
    _print2("dtor", "called");
}

typedef int _AtExit_t (void(*func)(void));  /* Py_AtExit() signature */

static void  __attribute__((constructor))
_ctor (void)
{
    _AtExit_t* _AtExit;
    _print2("ctor", "called");
    _AtExit = dlsym(RTLD_DEFAULT, "Py_AtExit");
    if (_AtExit) {
        _print2("dlsym Py_AtExit", ((*_AtExit)(_dtor) < 0 ? "failed!" : "OK"));
    } else {
        _print2("dlsym(Py_AtExit)", "failed!");
    }
}


#elif _USECASE == 4  /* weak Py_AtExit */

static void
_dtor (void)
{
    _print2("dtor", "called");
}

extern int Py_AtExit (void(*func)(void)) __attribute__((weak));

static void  __attribute__((constructor))
_ctor (void)
{
    _print2("ctor", "called");
    if (Py_AtExit) {
        _print2("weak Py_AtExit", (Py_AtExit(_dtor) < 0 ? "failed!" : "OK"));
    } else {
        _print2("weak Py_AtExit", "unresolved!");
    }
}


#else
# error #define _USECASE 1, 2, 3, or 4
#endif
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to