PythonEnablePdb option.

2005-11-03 Thread Graham Dumpleton

The documentation for the Python debugger support in mod_python states:

  Because pdb is an interactive tool, start httpd from the command line
  with the -DONE_PROCESS option when using this directive. As soon as  
your
  handler code is entered, you will see a Pdb prompt allowing you to  
step

  through the code and examine variables.

If you enable PythonEnablePdb but try to use Apache in its normal mode,
ie., not as a single foreground process, you will get an error:

  Mod_python error: PythonHandler mptest

  Traceback (most recent call last):

File  
/System/Library/Frameworks/Python.framework/Versions/2.3/lib/ 
python2.3/site-packages/mod_python/apache.py, line 301, in  
HandlerDispatch

  assert (type(result) == type(int())), \

  AssertionError: Handler 'mptest' returned invalid return code.

This occurs because the pdb module internally generates an error when
it somehow realises that it isn't being run in interactive mode. Rather
than this exception being propagated, it simply returns None which
causes the above error.

Even if running pdb in single process mode, if quit is entered into
pdb as a command, you will get a similar error.

With the thought of mod_python perhaps ignoring the PythonEnabledPdb
option when not run in single process mode, is there a way using the
apache.mpm_query() function or some other function of determining that
Apache is running in single process mode?

This will not solve the quit problem, for that rather than calling
pdb.runcall(), mod_python perhaps could implement an alternate variant  
of

the Bdb.runcall() which is ultimately called which raises an appropriate
Apache error more appropriate in context of mod_python when the BdbQuit
exception is raised.

Anyone have any thoughts? Anyone use the pdb support?

Graham



Re: PythonEnablePdb option.

2005-11-03 Thread Gregory (Grisha) Trubetskoy


On Thu, 3 Nov 2005, Graham Dumpleton wrote:


With the thought of mod_python perhaps ignoring the PythonEnabledPdb
option when not run in single process mode, is there a way using the
apache.mpm_query() function or some other function of determining that
Apache is running in single process mode?


I wonder if simply examining sys.argv would work?

Grisha


Re: PythonEnablePdb option.

2005-11-03 Thread Graham Dumpleton
Graham Dumpleton wrote ..
 Grisha wrote ..
  
  On Thu, 3 Nov 2005, Graham Dumpleton wrote:
  
   With the thought of mod_python perhaps ignoring the PythonEnabledPdb
   option when not run in single process mode, is there a way using the
   apache.mpm_query() function or some other function of determining that
   Apache is running in single process mode?
  
  I wonder if simply examining sys.argv would work?
 
 Can't be done this way as sys.argv doesn't even exist in mod_python.

 ...
 
 Also need to sort out how -DONE_PROCESS and -X options are
 different, as pdb support also works if -X option is used. This is
 probably dangerous though to use as you still potentially get
 child processes and thus fire off more than one request and they
 will fight over standard input.

To determine if -DONE_PROCESS was used on the command line,
noting that -X is equivalent to -DONE_PROCESS and -DNO_DETATCH,
one can use in the Apache configuration file:

  IfDefine ONE_PROCESS
  PythonEnablePdb On
  /IfDefine

As far as I can tell, the IfDefine directive uses the Apache C function:

  ap_exists_config_define()

Ie., the defined symbol is the argument:

  ap_exists_config_define(ONE_PROCESS)

Unless I am missing something, there is no equivalent to being able
to do IfDefine from within Python code executing inside of mod_python.
It sounds though that in this case with pdb that it might be a potentially
useful feature.

Thus, what do people think about a new function:

  apache.exists_config_define(arg)

Graham


[jira] Commented: (MODPYTHON-77) The multiple interpreter concept of mod_python is broken for Python extension modules since Python 2.3

2005-11-03 Thread Graham Dumpleton (JIRA)
[ 
http://issues.apache.org/jira/browse/MODPYTHON-77?page=comments#action_12356739 
] 

Graham Dumpleton commented on MODPYTHON-77:
---

There are now so many different suggestions on this that it is all too 
confusing.

In respect of latest suggested change to release_interpreter(), this code 
wasn't based on latest code from 3.2 betas and therefore doesn't include fix 
for where Python doesn't support threading at all. Ie., the base code on which 
it should have been made was:

static void release_interpreter(void)
{
PyThreadState *tstate = PyThreadState_Get();
#ifdef WITH_THREAD
PyEval_ReleaseThread(tstate);
#else
PyThreadState_Swap(NULL);
#endif
PyThreadState_Delete(tstate);
}

Ie., new call to PyThreadState_Swap() not factored in.

I will refrain from posting what it perhaps should be so as not to make things 
worse.

In terms of the comment smallest required change, I am currently taking this 
to mean that the most minimal change is still to install first interpreter as 
main_interpreter and then to change release_interpreter() as suggested in 
previous post.

Before anyone else posts any code, let me independently work out some changes 
from scratch and thus verify the fixes or not. :-(


 The multiple interpreter concept of mod_python is broken for Python extension 
 modules since Python 2.3
 --

  Key: MODPYTHON-77
  URL: http://issues.apache.org/jira/browse/MODPYTHON-77
  Project: mod_python
 Type: Bug
   Components: core
 Versions: 3.1.4
  Environment: Python = 2.3
 Reporter: Boyan Boyadjiev
  Attachments: diff.txt, diff2.txt, diff3.txt, gil_test.c, gilstate.tar.gz, 
 mod_python.c, mod_python.c.diff, mod_python.h.diff, src.zip

 The multiple interpreter concept of mod_python is broken for Python extension 
 modules since Python 2.3 because of the PEP 311 (Simplified Global 
 Interpreter Lock Acquisition for Extensions):
 ...
 Limitations and Exclusions
 This proposal identifies a solution for extension authors with
 complex multi-threaded requirements, but that only require a
 single PyInterpreterState.  There is no attempt to cater for
 extensions that require multiple interpreter states.  At the time
 of writing, no extension has been identified that requires
 multiple PyInterpreterStates, and indeed it is not clear if that
 facility works correctly in Python itself.
 ...
 For mod_python this means, that complex Python extensions won't work any more 
 with Python = 2.3, because they are supposed to work only with the first 
 interpreter state initialized for the current process (a problem we 
 experienced). The first interpreter state is not used by mod_python after the 
 python_init is called. 
 One solution, which works fine for me, is to save the first interpreter state 
 into the interpreters dictionary in the function python_init 
 (MAIN_INTERPRETER is used as a key):
 static int python_init(apr_pool_t *p, apr_pool_t *ptemp,
apr_pool_t *plog, server_rec *s)
 {
 ...
 /* initialize global Python interpreter if necessary */
 if (! Py_IsInitialized())
 {
 /* initialze the interpreter */
 Py_Initialize();
 #ifdef WITH_THREAD
 /* create and acquire the interpreter lock */
 PyEval_InitThreads();
 #endif
 /* create the obCallBack dictionary */
 interpreters = PyDict_New();
 if (! interpreters) {
 ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, s,
  python_init: PyDict_New() failed! No more memory?);
 exit(1);
 }
 {   
 /*
 Workaround PEP 311 - Simplified Global Interpreter Lock 
 Acquisition for Extensions
 BEGIN
 */
 PyObject *p = 0;
 interpreterdata * idata = (interpreterdata 
 *)malloc(sizeof(interpreterdata));
 PyThreadState* currentThreadState = PyThreadState_Get();
 PyInterpreterState *istate = currentThreadState-interp;
 idata-istate = istate;
 /* obcallback will be created on first use */
 idata-obcallback = NULL;
 p = PyCObject_FromVoidPtr((void ) idata, NULL); /*p-refcout = 1*/
 PyDict_SetItemString(interpreters, MAIN_INTERPRETER, p); 
 /*p-refcout = 2*/
 Py_DECREF(p); /*p-refcout = 1*/
 /*
 END
 Workaround PEP 311 - Simplified Global Interpreter Lock 
 Acquisition for Extensions
 */
 }
 /* Release the thread state because we will never use
  * the main interpreter, only sub interpreters created later. */
 PyThreadState_Swap(NULL);
 #ifdef WITH_THREAD
 /* release the lock; now other threads can run */
 PyEval_ReleaseLock();
 #endif
 }