Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
commit
fc12f73fba
@ -121,7 +121,6 @@ data/Makefile
|
|||||||
lib/Makefile
|
lib/Makefile
|
||||||
lib/src/Makefile
|
lib/src/Makefile
|
||||||
lib/python/Makefile
|
lib/python/Makefile
|
||||||
lib/threadframe/Makefile
|
|
||||||
services/Makefile
|
services/Makefile
|
||||||
services/presence/Makefile
|
services/presence/Makefile
|
||||||
services/presence2/Makefile
|
services/presence2/Makefile
|
||||||
|
@ -1 +1 @@
|
|||||||
SUBDIRS = src python threadframe
|
SUBDIRS = src python
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
PYTHON:= $(shell python -c "import sys;print '%%d%%d' %% sys.version_info[:2]")
|
|
||||||
|
|
||||||
threadframe.pyd: threadframe.o libpython$(PYTHON).a
|
|
||||||
dllwrap --dllname threadframe.pyd --driver-name=gcc --def threadframe.def -o threadframe.pyd threadframe.o -s --entry _DllMain@12 --target=i386-mingw32 -L. -lpython$(PYTHON)
|
|
||||||
|
|
||||||
threadframe.o: threadframemodule.c
|
|
||||||
gcc -I"C:\Program Files\Python$(PYTHON)\include" -O3 -c -o $@ -DNDEBUG $<
|
|
||||||
libpython$(PYTHON).a: python$(PYTHON).def C:\WINNT\system32\python$(PYTHON).dll
|
|
||||||
dlltool --dllname python$(PYTHON).dll --def python$(PYTHON).def --output-lib libpython$(PYTHON).a
|
|
||||||
|
|
||||||
python$(PYTHON).def: C:\WINNT\system32\python$(PYTHON).dll
|
|
||||||
pexports C:\WINNT\system32\python$(PYTHON).dll > python$(PYTHON).def
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-del threadframe.pyd
|
|
||||||
-del libpython$(PYTHON).a
|
|
||||||
-del threadframe.o
|
|
||||||
-del python$(PYTHON).def
|
|
@ -1,6 +0,0 @@
|
|||||||
INCLUDES = $(PYTHON_INCLUDES)
|
|
||||||
|
|
||||||
threadframedir = $(pyexecdir)
|
|
||||||
threadframe_la_LDFLAGS = -module -avoid-version
|
|
||||||
threadframe_LTLIBRARIES = threadframe.la
|
|
||||||
threadframe_la_SOURCES = threadframemodule.c
|
|
@ -1,34 +0,0 @@
|
|||||||
Note on the License
|
|
||||||
Dan Williams <dcbw at redhat com> 2006-08-16
|
|
||||||
|
|
||||||
Since 'setup.py' specifies the "Python" license, it is assumed that the
|
|
||||||
threadframe package is distributed under that license, even though there
|
|
||||||
is no license header at the top of the source file.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Obtaining tracebacks on other threads in Python
|
|
||||||
===============================================
|
|
||||||
by Fazal Majid (www.majid.info), 2004-06-10
|
|
||||||
|
|
||||||
David Beazley added advanced debugging functions to the Python interpreter,
|
|
||||||
and they have been folded into the 2.2 release. Guido van Rossum added in
|
|
||||||
Python 2.3 the thread ID to the interpreter state structure, and this allows
|
|
||||||
us to produce a dictionary mapping thread IDs to frames.
|
|
||||||
|
|
||||||
I used these hooks to build a debugging module that is useful when you
|
|
||||||
are looking for deadlocks in a multithreaded application. I've built
|
|
||||||
and tested this only on Solaris 8/x86, but the code should be pretty
|
|
||||||
portable.
|
|
||||||
|
|
||||||
Of course, I disclaim any liability if this code should crash your system,
|
|
||||||
erase your homework, eat your dog (who also ate your homework) or otherwise
|
|
||||||
have any undesirable effect.
|
|
||||||
|
|
||||||
Building and installing
|
|
||||||
=======================
|
|
||||||
|
|
||||||
Download threadframe-0.2.tar.gz. You can use the Makefile or the setup.py
|
|
||||||
script. There is a small test program test.py that illustrates how to use this
|
|
||||||
module to dump stack frames of all the Python interpreter threads. A sample
|
|
||||||
run is available for your perusal.
|
|
@ -1,37 +0,0 @@
|
|||||||
Script started on Thu 10 Jun 2004 07:23:38 PM PDT
|
|
||||||
bayazid ~/threadframe-0.2>python test.py
|
|
||||||
ident of main thread is: 1
|
|
||||||
|
|
||||||
launching daemon thread... done
|
|
||||||
launching self-deadlocking thread... done
|
|
||||||
launching thread that will die before the end... done
|
|
||||||
[4] Spam spam spam spam. Lovely spam! Wonderful spam!
|
|
||||||
[4] Spam spam spam spam. Lovely spam! Wonderful spam!
|
|
||||||
[4] Spam spam spam spam. Lovely spam! Wonderful spam!
|
|
||||||
[4] Spam spam spam spam. Lovely spam! Wonderful spam!
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
[1] 4
|
|
||||||
File "test.py", line 56, in ?
|
|
||||||
traceback.print_stack(frame)
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
[4] 4
|
|
||||||
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
|
|
||||||
self.run()
|
|
||||||
File "test.py", line 6, in run
|
|
||||||
time.sleep(1)
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
[5] 4
|
|
||||||
File "/usr/local/lib/python2.3/threading.py", line 436, in __bootstrap
|
|
||||||
self.run()
|
|
||||||
File "test.py", line 13, in run
|
|
||||||
U_lock.acquire()
|
|
||||||
------------------------------------------------------------------------
|
|
||||||
[6] 3
|
|
||||||
File "/usr/local/lib/python2.3/threading.py", line 455, in __bootstrap
|
|
||||||
pass
|
|
||||||
File "test.py", line 20, in run
|
|
||||||
V_event.wait()
|
|
||||||
File "/usr/local/lib/python2.3/threading.py", line 352, in wait
|
|
||||||
self.__cond.release()
|
|
||||||
File "/usr/local/lib/python2.3/threading.py", line 235, in wait
|
|
||||||
self._acquire_restore(saved_state)
|
|
@ -1,21 +0,0 @@
|
|||||||
from distutils.core import setup
|
|
||||||
from distutils.extension import Extension
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name = 'threadframe',
|
|
||||||
version = '0.2',
|
|
||||||
description = "Advanced thread debugging extension",
|
|
||||||
long_description = "Obtaining tracebacks on other threads than the current thread",
|
|
||||||
url = 'http://www.majid.info/mylos/stories/2004/06/10/threadframe.html',
|
|
||||||
maintainer = 'Fazal Majid',
|
|
||||||
maintainer_email = 'threadframe@majid.info',
|
|
||||||
license = 'Python',
|
|
||||||
platforms = [],
|
|
||||||
keywords = ['threading', 'thread'],
|
|
||||||
|
|
||||||
ext_modules=[
|
|
||||||
Extension('threadframe',
|
|
||||||
['threadframemodule.c'],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
@ -1,57 +0,0 @@
|
|||||||
import sys, time, threading, thread, os, traceback, threadframe, pprint
|
|
||||||
# daemon thread that spouts Monty Pythonesque nonsense
|
|
||||||
class T(threading.Thread):
|
|
||||||
def run(self):
|
|
||||||
while 1:
|
|
||||||
time.sleep(1)
|
|
||||||
print '[%d] Spam spam spam spam. Lovely spam! Wonderful spam!' % ( thread.get_ident(), )
|
|
||||||
# thread that cause a deliberate deadlock with itself
|
|
||||||
U_lock = threading.Lock()
|
|
||||||
class U(threading.Thread):
|
|
||||||
def run(self):
|
|
||||||
U_lock.acquire()
|
|
||||||
U_lock.acquire()
|
|
||||||
# thread that will exit after the thread frames are extracted but before
|
|
||||||
# they are printed
|
|
||||||
V_event = threading.Event()
|
|
||||||
class V(threading.Thread):
|
|
||||||
def run(self):
|
|
||||||
V_event.clear()
|
|
||||||
V_event.wait()
|
|
||||||
|
|
||||||
print 'ident of main thread is: %d' % (thread.get_ident(),)
|
|
||||||
print
|
|
||||||
print 'launching daemon thread...',
|
|
||||||
T().start()
|
|
||||||
print 'done'
|
|
||||||
print 'launching self-deadlocking thread...',
|
|
||||||
U().start()
|
|
||||||
print 'done'
|
|
||||||
print 'launching thread that will die before the end...',
|
|
||||||
v = V()
|
|
||||||
v.start()
|
|
||||||
print 'done'
|
|
||||||
|
|
||||||
time.sleep(5)
|
|
||||||
|
|
||||||
# Python 2.2 does not support threadframe.dict()
|
|
||||||
if sys.hexversion < 0x02030000:
|
|
||||||
frames = threadframe.threadframe()
|
|
||||||
else:
|
|
||||||
frames = threadframe.dict()
|
|
||||||
|
|
||||||
# signal the thread V to die, then wait for it to oblige
|
|
||||||
V_event.set()
|
|
||||||
v.join()
|
|
||||||
|
|
||||||
if sys.hexversion < 0x02030000:
|
|
||||||
for frame in frames:
|
|
||||||
print '-' * 72
|
|
||||||
print 'frame ref count = %d' % sys.getrefcount(frame)
|
|
||||||
traceback.print_stack(frame)
|
|
||||||
else:
|
|
||||||
for thread_id, frame in frames.iteritems():
|
|
||||||
print '-' * 72
|
|
||||||
print '[%s] %d' % (thread_id, sys.getrefcount(frame))
|
|
||||||
traceback.print_stack(frame)
|
|
||||||
os._exit(0)
|
|
@ -1,3 +0,0 @@
|
|||||||
EXPORTS
|
|
||||||
initthreadframe
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
* module to access the stack frame of all Python interpreter threads
|
|
||||||
*
|
|
||||||
* works on Solaris and OS X, portability to other OSes unknown
|
|
||||||
*
|
|
||||||
* Fazal Majid, 2002-10-11
|
|
||||||
*
|
|
||||||
* with contributions from Bob Ippolito (http://bob.pycs.net/)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2002-2004 Kefta Inc.
|
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Python.h"
|
|
||||||
#include "compile.h"
|
|
||||||
#include "frameobject.h"
|
|
||||||
#include "patchlevel.h"
|
|
||||||
|
|
||||||
static PyObject *
|
|
||||||
threadframe_threadframe(PyObject *self, PyObject *args) {
|
|
||||||
PyInterpreterState *interp;
|
|
||||||
PyThreadState *tstate;
|
|
||||||
PyFrameObject *frame;
|
|
||||||
PyListObject *frames;
|
|
||||||
|
|
||||||
frames = (PyListObject*) PyList_New(0);
|
|
||||||
if (! frames) return NULL;
|
|
||||||
|
|
||||||
/* Walk down the interpreters and threads until we find the one
|
|
||||||
matching the supplied thread ID. */
|
|
||||||
for (interp = PyInterpreterState_Head(); interp != NULL;
|
|
||||||
interp = interp->next) {
|
|
||||||
for(tstate = interp->tstate_head; tstate != NULL;
|
|
||||||
tstate = tstate->next) {
|
|
||||||
frame = tstate->frame;
|
|
||||||
if (! frame) continue;
|
|
||||||
Py_INCREF(frame);
|
|
||||||
PyList_Append((PyObject*) frames, (PyObject*) frame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (PyObject*) frames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the PyThreadState gained a thread_id member only in 2.3rc1 */
|
|
||||||
static PyObject *
|
|
||||||
threadframe_dict(PyObject *self, PyObject *args) {
|
|
||||||
#if PY_VERSION_HEX < 0x02030000
|
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
|
||||||
"threadframe.dict() requires Python 2.3 or later");
|
|
||||||
return NULL;
|
|
||||||
#else
|
|
||||||
PyInterpreterState *interp;
|
|
||||||
PyThreadState *tstate;
|
|
||||||
PyFrameObject *frame;
|
|
||||||
PyObject *frames;
|
|
||||||
|
|
||||||
frames = (PyObject*) PyDict_New();
|
|
||||||
if (! frames) return NULL;
|
|
||||||
|
|
||||||
/* Walk down the interpreters and threads until we find the one
|
|
||||||
matching the supplied thread ID. */
|
|
||||||
for (interp = PyInterpreterState_Head(); interp != NULL;
|
|
||||||
interp = interp->next) {
|
|
||||||
for(tstate = interp->tstate_head; tstate != NULL;
|
|
||||||
tstate = tstate->next) {
|
|
||||||
PyObject *thread_id;
|
|
||||||
frame = tstate->frame;
|
|
||||||
if (! frame) continue;
|
|
||||||
thread_id = PyInt_FromLong(tstate->thread_id);
|
|
||||||
PyDict_SetItem(frames, thread_id, (PyObject*)frame);
|
|
||||||
Py_DECREF(thread_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return frames;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static char threadframe_doc[] =
|
|
||||||
"Returns a list of frame objects for all threads.\n"
|
|
||||||
"(equivalent to dict().values() on 2.3 and later).";
|
|
||||||
|
|
||||||
static char threadframe_dict_doc[] =
|
|
||||||
"Returns a dictionary, mapping for all threads the thread ID\n"
|
|
||||||
"(as returned by thread.get_ident() or by the keys to threading._active)\n"
|
|
||||||
"to the corresponding frame object.\n"
|
|
||||||
"Raises NotImplementedError on Python 2.2.";
|
|
||||||
|
|
||||||
/* List of functions defined in the module */
|
|
||||||
|
|
||||||
static PyMethodDef threadframe_methods[] = {
|
|
||||||
{"threadframe", threadframe_threadframe, METH_VARARGS, threadframe_doc},
|
|
||||||
{"dict", threadframe_dict, METH_VARARGS, threadframe_dict_doc},
|
|
||||||
{NULL, NULL} /* sentinel */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Initialization function for the module (*must* be called initthreadframe) */
|
|
||||||
|
|
||||||
static char module_doc[] =
|
|
||||||
"Debugging module to extract stack frames for all Python interpreter heads.\n"
|
|
||||||
"Useful in conjunction with traceback.print_stack().\n";
|
|
||||||
|
|
||||||
DL_EXPORT(void)
|
|
||||||
initthreadframe(void)
|
|
||||||
{
|
|
||||||
PyObject *m;
|
|
||||||
|
|
||||||
/* Create the module and add the functions */
|
|
||||||
m = Py_InitModule3("threadframe", threadframe_methods, module_doc);
|
|
||||||
}
|
|
@ -865,17 +865,12 @@ class PresenceService(object):
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
from sugar import TracebackUtils
|
|
||||||
loop = gobject.MainLoop()
|
loop = gobject.MainLoop()
|
||||||
ps = PresenceService()
|
ps = PresenceService()
|
||||||
tbh = TracebackUtils.TracebackHelper()
|
|
||||||
try:
|
try:
|
||||||
loop.run()
|
loop.run()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print 'Ctrl+C pressed, exiting...'
|
print 'Ctrl+C pressed, exiting...'
|
||||||
|
|
||||||
del tbh
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -28,7 +28,6 @@ import gobject
|
|||||||
from sugar import logger
|
from sugar import logger
|
||||||
from sugar import profile
|
from sugar import profile
|
||||||
from sugar import env
|
from sugar import env
|
||||||
from sugar import TracebackUtils
|
|
||||||
|
|
||||||
logger.cleanup()
|
logger.cleanup()
|
||||||
logger.start('shell')
|
logger.start('shell')
|
||||||
@ -86,11 +85,9 @@ model = ShellModel()
|
|||||||
service = ShellService(model)
|
service = ShellService(model)
|
||||||
shell = Shell(model)
|
shell = Shell(model)
|
||||||
|
|
||||||
tbh = TracebackUtils.TracebackHelper()
|
|
||||||
try:
|
try:
|
||||||
gtk.main()
|
gtk.main()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print 'Ctrl+C pressed, exiting...'
|
print 'Ctrl+C pressed, exiting...'
|
||||||
del tbh
|
|
||||||
|
|
||||||
os.remove(dsba_file)
|
os.remove(dsba_file)
|
||||||
|
@ -7,5 +7,4 @@ sugar_PYTHON = \
|
|||||||
env.py \
|
env.py \
|
||||||
logger.py \
|
logger.py \
|
||||||
profile.py \
|
profile.py \
|
||||||
TracebackUtils.py \
|
|
||||||
util.py
|
util.py
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
# Copyright (C) 2006, Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# This library is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the GNU Lesser General Public
|
|
||||||
# License as published by the Free Software Foundation; either
|
|
||||||
# version 2 of the License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This library is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
# Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Lesser General Public
|
|
||||||
# License along with this library; if not, write to the
|
|
||||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
||||||
# Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
|
|
||||||
haveThreadframe = True
|
|
||||||
try:
|
|
||||||
import threadframe
|
|
||||||
except ImportError:
|
|
||||||
haveThreadframe = False
|
|
||||||
|
|
||||||
class TracebackHelper(object):
|
|
||||||
def __init__(self):
|
|
||||||
fname = "%s-%d" % (os.path.basename(sys.argv[0]), os.getpid())
|
|
||||||
self._fpath = os.path.join("/tmp", fname)
|
|
||||||
print "Tracebacks will be written to %s on SIGUSR1" % self._fpath
|
|
||||||
signal.signal(signal.SIGUSR1, self._handler)
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
try:
|
|
||||||
os.remove(self._fpath)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def _handler(self, signum, pframe):
|
|
||||||
f = open(self._fpath, "a")
|
|
||||||
if not haveThreadframe:
|
|
||||||
f.write("Threadframe not installed. No traceback available.\n")
|
|
||||||
else:
|
|
||||||
frames = threadframe.dict()
|
|
||||||
for thread_id, frame in frames.iteritems():
|
|
||||||
f.write(('-' * 79) + '\n')
|
|
||||||
f.write('[Thread %s] %d' % (thread_id, sys.getrefcount(frame)) + '\n')
|
|
||||||
traceback.print_stack(frame, limit=None, file=f)
|
|
||||||
f.write("\n")
|
|
||||||
f.write('\n')
|
|
||||||
f.close()
|
|
Loading…
Reference in New Issue
Block a user