Message197

Author bckfnn
Recipients
Date 2000-11-18.19:51:37
SpamBayes Score
Marked as misclassified
Message-id
In-reply-to
Content
I am building a (Java based) system, where the user can use JPython commands 
to script some actions. I want to provide a facility which allows the user to
trace his script in a logging window and also to interrupt his script.
I therefore run the script under a bdb derived debugger. My user_line method
prints the
tracing information into the logging window and checks an interrupt button:

from bdb import Bdb
import string

userInterrupt = 'tracing.userInterrupt'

class tracing(Bdb):

...
...

	def user_line(self, frame):
		import linecache, string
		name = frame.f_code.co_name
		if not name: name = '???'
		fn = self.canonic(frame.f_code.co_filename)
		if self.checkfile (fn, name): return
		line = linecache.getline(fn, frame.f_lineno)
		self.executor.addTraceLine ('+++ %s %d %s: %s' %
			(fn, frame.f_lineno, name, string.strip(line)))
		if self.executor.isInterrupted ( ):
			self.executor.addTraceLine ("is interrupted")
---->>>>		raise userInterrupt
...
...

If the interrupt button is pressed, it throws an exception which is caught just
outside the user script.

This works perfectly, but only once. The reason can be found in 
org.python.core.PythonTraceFunction:

    private synchronized TraceFunction safeCall(PyFrame frame, String label,
                                                PyObject arg)
    {
        ThreadState ts = Py.getThreadState();
        if (ts.tracing)
            return null;

        if (tracefunc == null)
            return null;

        ts.tracing = true;
        PyObject ret = tracefunc.__call__(frame, new PyString(label), arg);
-->     ts.tracing = false;
        if (ret == tracefunc)
            return this;
        if (ret == Py.None)
            return null;
        return new PythonTraceFunction(ret);
    }

When an exception is thrown in the trace function, the ts.tracing member is
never
reset to false.

I have modified the function as follows:

    private synchronized TraceFunction safeCall(PyFrame frame, String label,
                                                PyObject arg)
    {
        ThreadState ts = Py.getThreadState();
        if (ts.tracing)
            return null;

        if (tracefunc == null)
            return null;

        ts.tracing = true;
	TraceFunction res = null;
	try {
	    PyObject ret = tracefunc.__call__(frame, new PyString(label), arg);
	    ts.tracing = false;
	    if (ret == tracefunc)
		res = this;
	    if (ret == Py.None)
		res = null;
	    res = new PythonTraceFunction(ret);
	}
	finally {
	    ts.tracing = false;
	}
	return res;
    }

This solves my problem. I am not sure however, if this breaks anything else.

I am a little reluctant to use a self-patched JPython system. So if you know a
different workaround which does not require modifications of JPython, please
let
me know.

Thanks for your effort and also for providing such a great tool,
    Paul

History
Date User Action Args
2008-02-20 17:16:45adminlinkissue222874 messages
2008-02-20 17:16:45admincreate