Create a background thread from WSGI script file.

The thread should loop, doing a sleep of a few seconds on each loop.

That thread would then look for the existence of a specific file.

If the file already existed when first started, when its modification
time changes, dump out the stack trace of all Python threads in
interpreter.

If the file doesn't initially exist when first started, when it does
appear, dump out the stack trace of all Python threads in interpreter.
Remember the modification time so that on subsequent time through
loop, look at modification time instead.

This should be fairly trivial to get going and would do it myself it
had time, but trying to get some stuff out of the way at the moment.

To get you started, use the loop/sleep code from:

http://code.google.com/p/modwsgi/wiki/ReloadingSourceCode#Monitoring_For_Code_Changes

This uses a timed queue get and atexit handlers to try and shutdown
cleanly on process shutdown and no cause a crash. Thus:

import os
import sys
import time
import signal
import threading
import atexit
import Queue

def _monitor():
    while 1:
        # Perform the check for creation of file or change in
modification time and if file touched, then dump stack trace.

        ... add code here

        # Go to sleep for specified interval.

        try:
            return _queue.get(timeout=_interval)
        except:
            pass

_thread = threading.Thread(target=_monitor)
_thread.setDaemon(True)

def _exiting():
    try:
        _queue.put(True)
    except:
        pass
    _thread.join()

atexit.register(_exiting)

def track(path):
    if not path in _files:
        _files.append(path)

def start(interval=1.0):
    global _interval
    if interval < _interval:
        _interval = interval

    global _running
    _lock.acquire()
    if not _running:
        prefix = 'monitor (pid=%d):' % os.getpid()
        print >> sys.stderr, '%s Starting change monitor.' % prefix
        _running = True
        _thread.start()
    _lock.release()

Graham

On 15 September 2010 10:39, Charles Duffy <[email protected]> wrote:
> I am indeed sending the signal to the daemon process; as such, the
> explanation you give is consistent with observed behavior.
>
> My goal, similar to that expressed by Jeff in his prior thread on the
> subject, is to provide a means to dump a stack trace to stderr on
> request, allowing a glimpse into the state of of an unresponsive
> thread; with OS signals unavailable, I'm at a loss for ways to do this
> short of a script using gdb macros to attach and introspect -- perhaps
> an even more fragile approach, as the pystack macro provided by the
> Python team is known to occasionally crash the interpreter.
>
> (Well -- perhaps this isn't the *only* way to accomplish such a thing.
> For instance, one could have each daemon process spawn a separate
> thread which opens a socket, perhaps named by PID, and block on a 1-
> byte read, dumping a stack trace of all other threads in its view
> whenever that socket is written to. However, the obvious drawbacks re:
> implementation complexity and overhead make me hesitant to pursue that
> approach).
>
> On Sep 14, 7:19 pm, Graham Dumpleton <[email protected]>
> wrote:
>> What process are you sending the signal to?
>>
>> From memory such signal fiddles will not work with daemon mode
>> processes as the main thread which handles signals in Python is never
>> used in daemon mode and all requests are handled in secondary foreign
>> threads.
>>
>> What are you wanting to do in response to the signal anyway?
>>
>> In general I highly recommend not trying to do anything with signals
>> as you don't control the process execution environment, Apache does,
>> and fiddling with signals can upset the operation of Apache.
>>
>> Graham
>>
>> On 15 September 2010 03:29, Charles Duffy <[email protected]> wrote:
>>
>>
>>
>> > Howdy! I'm trying to implement something similar to what Jeff Jenkins
>> > described in the thread "mod_wsgi and signals" (http://
>> > groups.google.com/group/modwsgi/browse_frm/thread/353e2e782921d5d3/
>> > d377935ea65e985c). The limitations described in that thread (deferred
>> > delivery for threads sitting in the Apache main loop rather than
>> > Python code) are acceptable for my intended use case.
>>
>> > My setup should be fairly simple:
>> > - I'm using the prefork MPM with Apache 2.2.3 on CentOS, against a
>> > locally built Python 2.6.4
>> > - I'm currently targeting SIGUSR2 -- as (1) its default action is to
>> > be ignored, and (2) Apache doesn't use it for anything as far as I
>> > know.
>> > - I'm calling signal.signal() directly within the .wsgi file specified
>> > by a "WSGIDaemonProcess" directive.
>>
>> > However, something seems to be very wrong:
>>
>> > - Even with an explicit "WSGIRestrictSignal On", the warning
>> > indicating that a signal handler registration was attempted and
>> > suppressed is not logged -- even with "LogLevel info" set. Calling
>> > signal.signal() twice returns the previously-set handler, implying
>> > that the handler is in fact put in place.
>> > - While I'm using USR2, for which the default action is ignore, the
>> > child process exits when the signal is received -- whether or not I've
>> > run my code registering this handler. The associated log message is
>> > akin to the following: [notice] child pid 54321 exit signal User
>> > defined signal 2 (12)
>> > - Calling signal.signal() to register the handler returns that it's
>> > already using the desired function, but sending the process the
>> > relevant signal still causes it to die (again, contrary to the usual
>> > default disposition for SIGUSR2, which is SIG_IGN).
>>
>> > I've tried to follow in Jeff's footsteps and switching to SIGQUIT;
>> > however, this followed its default (erroneous exit) behavior.
>>
>> > Any pointers?
>>
>> > --
>> > You received this message because you are subscribed to the Google Groups 
>> > "modwsgi" group.
>> > To post to this group, send email to [email protected].
>> > To unsubscribe from this group, send email to 
>> > [email protected].
>> > For more options, visit this group 
>> > athttp://groups.google.com/group/modwsgi?hl=en.
>
> --
> You received this message because you are subscribed to the Google Groups 
> "modwsgi" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to 
> [email protected].
> For more options, visit this group at 
> http://groups.google.com/group/modwsgi?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"modwsgi" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/modwsgi?hl=en.

Reply via email to