Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Dan Williams 2007-04-06 15:29:14 -04:00
commit fc12f73fba
14 changed files with 1 additions and 352 deletions

View File

@ -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

View File

@ -1 +1 @@
SUBDIRS = src python threadframe SUBDIRS = src python

View File

@ -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

View File

@ -1,6 +0,0 @@
INCLUDES = $(PYTHON_INCLUDES)
threadframedir = $(pyexecdir)
threadframe_la_LDFLAGS = -module -avoid-version
threadframe_LTLIBRARIES = threadframe.la
threadframe_la_SOURCES = threadframemodule.c

View File

@ -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.

View File

@ -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)

View File

@ -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'],
),
],
)

View File

@ -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)

View File

@ -1,3 +0,0 @@
EXPORTS
initthreadframe

View File

@ -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);
}

View File

@ -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()

View File

@ -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)

View 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

View File

@ -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()