Skip to content

Commit

Permalink
This shall be 2.5
Browse files Browse the repository at this point in the history
  • Loading branch information
gtrubetskoy committed Sep 5, 2000
1 parent ccf254e commit 124eec7
Show file tree
Hide file tree
Showing 3 changed files with 234 additions and 5 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Sep 5 2000 - 2.5 released.

Sep 4 2000 - Added the PythonCleanupHandler.

Sep 4 2000 - Added req.register_cleanup(). Still need server.register_cleanup(),
as well as a PythonCleanupHandler.

Expand Down
35 changes: 33 additions & 2 deletions doc/directives.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<!-- $Id: directives.html,v 1.13 2000/09/04 15:54:56 gtrubetskoy Exp $ -->
<!-- $Id: directives.html,v 1.14 2000/09/05 12:46:55 gtrubetskoy Exp $ -->

<html>
<head>
Expand All @@ -27,6 +27,7 @@ <h1>Apache Configuration Directives</h1>
<li><a href="#PythonHandler">PythonHandler</a>
<li><a href="#PythonInitHandler">PythonInitHandler</a>
<li><a href="#PythonLogHandler">PythonLogHandler</a>
<li><a href="#PythonCleanupHandler">PythonCleanupHandler</a>
<br><br>
<a href="#other">Other Directives</a>
<br><br>
Expand Down Expand Up @@ -333,6 +334,36 @@ <h2><a name="PythonLogHandler">PythonLogHandler</a></h2>
This routine is called to perform any module-specific logging activities
over and above the normal server things.
<p>
<hr>
<h2><a name="PythonCleanupHandler">PythonCleanupHandler</a></h2>
<a href="http://www.apache.org/docs/mod/directive-dict.html#Syntax" rel="Help">
<strong>Syntax:</strong></a> <a href="#HandlerSyntax"><em>Python*Handler syntax</em></a><br>
<a href="http://www.apache.org/docs/mod/directive-dict.html#Default" rel="Help">
<strong>Default:</strong></A> <code>None</code><br>
<a href="http://www.apache.org/docs/mod/directive-dict.html#Context" rel="Help">
<strong>Context:</strong></a> server config, virtual host, directory, htaccess<br>
<a href="http://www.apache.org/docs/mod/directive-dict.html#Override" rel="Help">
<strong>Override:</strong></a> not None<br>
<a href="http://www.apache.org/docs/mod/directive-dict.html#Module" rel="Help">
<strong>Module:</strong></a> mod_python.c

<p>
This is the very last handler, called just before the request object
is destroyed by Apache.
<p>
Unlike all the other handlers, the return value of this handler is ignored.
Any errors will be logged to the error log, but will not be sent to the
client, even if PythonDebug is On.
<p>
This handler is not a valid argument to the rec.add_handler() function.
For dynamic clean up registration, use req.register_cleanup().
<p>
Once cleanups have started, it is not possible to register more of them.
Terefore, req.register_cleanup() has no effect within this handler.
<p>
Cleanups registered with this directive will execute <em>after</em> cleanups
registered with req.register_cleanup().
<p>
<hr>
<a name="other"><h1>Other Directives</h1></a>
<hr>
Expand Down Expand Up @@ -591,7 +622,7 @@ <h2><a name="PythonPath">PythonPath</a></h2>
<hr>
<!-- Created: Sat May 6 21:05:39 EDT 2000 -->
<!-- hhmts start -->
Last modified: Sat Sep 2 15:06:30 EDT 2000
Last modified: Mon Sep 4 21:45:23 EDT 2000
<!-- hhmts end -->
</body>
</html>
200 changes: 197 additions & 3 deletions src/mod_python.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
*
* mod_python.c
*
* $Id: mod_python.c,v 1.28 2000/09/04 19:21:20 gtrubetskoy Exp $
* $Id: mod_python.c,v 1.29 2000/09/05 12:46:55 gtrubetskoy Exp $
*
* See accompanying documentation and source code comments
* for details.
Expand Down Expand Up @@ -2849,7 +2849,10 @@ static int python_handler(request_rec *req, char *handler)
/**
** python_cleanup
**
* This function gets called for registered cleanups
* This function gets called for clean ups registered
* with register_cleanup(). Clean ups registered via
* PythonCleanupHandler run in python_cleanup_handler()
* below.
*/

void python_cleanup(void *data)
Expand Down Expand Up @@ -2940,6 +2943,179 @@ void python_cleanup(void *data)
return;
}

/**
** python_cleanup_handler
**
* Runs handler registered via PythonCleanupHandler. Clean ups
* registered via register_cleanup() run in python_cleanup() above.
*
* This is a little too similar to python_handler, except the
* return of the function doesn't matter.
*/

void python_cleanup_handler(void *data)
{

request_rec *req = (request_rec *)data;
char *handler = "PythonCleanupHandler";
interpreterdata *idata;
requestobject *request_obj;
const char *s;
py_dir_config * conf;
const char * interpreter = NULL;
#ifdef WITH_THREAD
PyThreadState *tstate;
#endif

/* get configuration */
conf = (py_dir_config *) ap_get_module_config(req->per_dir_config, &python_module);

/* is there a handler? */
if (! ap_table_get(conf->directives, handler)) {
return;
}

/*
* determine interpreter to use
*/

if ((s = ap_table_get(conf->directives, "PythonInterpreter"))) {
/* forced by configuration */
interpreter = s;
}
else {
if ((s = ap_table_get(conf->directives, "PythonInterpPerDirectory"))) {
/* base interpreter on directory where the file is found */
if (ap_is_directory(req->filename))
interpreter = ap_make_dirstr_parent(req->pool,
ap_pstrcat(req->pool,
req->filename,
SLASH_S, NULL ));
else {
if (req->filename)
interpreter = ap_make_dirstr_parent(req->pool, req->filename);
else
/* very rare case, use global interpreter */
interpreter = NULL;
}
}
else if (ap_table_get(conf->directives, "PythonInterpPerServer")) {
interpreter = req->server->server_hostname;
}
else {
/* - default -
* base interpreter name on directory where the handler directive
* was last found. If it was in http.conf, then we will use the
* global interpreter.
*/

if (! s) {
s = ap_table_get(conf->dirs, handler);
if (strcmp(s, "") == 0)
interpreter = NULL;
else
interpreter = s;
}
}
}

#ifdef WITH_THREAD
/* acquire lock (to protect the interpreters dictionary) */
PyEval_AcquireLock();
#endif

/* get/create interpreter */
idata = get_interpreter_data(interpreter, req->server);

#ifdef WITH_THREAD
/* release the lock */
PyEval_ReleaseLock();
#endif

if (!idata) {
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, req,
"python_cleanup_handler: get_interpreter_data returned NULL!");
return;
}

#ifdef WITH_THREAD
/* create thread state and acquire lock */
tstate = PyThreadState_New(idata->istate);
PyEval_AcquireThread(tstate);
#endif

if (!idata->obcallback) {

idata->obcallback = make_obcallback();
/* we must have a callback object to succeed! */
if (!idata->obcallback)
{
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, req,
"python_cleanup_handler: make_obcallback returned no obCallBack!");
#ifdef WITH_THREAD
PyThreadState_Swap(NULL);
PyThreadState_Delete(tstate);
PyEval_ReleaseLock();
#endif
return;
}
}

/*
* make a note of which subinterpreter we're running under.
* this information is used by register_cleanup()
*/
if (interpreter)
ap_table_set(req->notes, "python_interpreter", interpreter);
else
ap_table_set(req->notes, "python_interpreter", GLOBAL_INTERPRETER);

/* create/acquire request object */
request_obj = get_request_object(req);

/* make a note of which handler we are in right now */
ap_table_set(req->notes, "python_handler", handler);

/* put the list of handlers on the hstack */
if ((s = ap_table_get(conf->directives, handler))) {
request_obj->hstack = ap_pstrdup(req->pool, ap_table_get(conf->directives,
handler));
}
if ((s = ap_table_get(req->notes, handler))) {
if (request_obj->hstack) {
request_obj->hstack = ap_pstrcat(req->pool, request_obj->hstack,
" ", s, NULL);
}
else {
request_obj->hstack = ap_pstrdup(req->pool, s);
}
}
/*
* Here is where we call into Python!
* This is the C equivalent of
* >>> obCallBack.Dispatch(request_object, handler)
*/
PyObject_CallMethod(idata->obcallback, "Dispatch", "Os",
request_obj, handler);

#ifdef WITH_THREAD
/* release the lock and destroy tstate*/
/* XXX Do not use
* . PyEval_ReleaseThread(tstate);
* . PyThreadState_Delete(tstate);
* because PyThreadState_delete should be done under
* interpreter lock to work around a bug in 1.5.2 (see patch to pystate.c 2.8->2.9)
*/
PyThreadState_Swap(NULL);
PyThreadState_Delete(tstate);
PyEval_ReleaseLock();
#endif

/* unlike python_handler, there is nothing to return */
return;
}


/**
** directive_PythonImport
**
Expand Down Expand Up @@ -3192,6 +3368,10 @@ static const char *directive_PythonAuthzHandler(cmd_parms *cmd, void * mconfig,
const char *val) {
return python_directive(cmd, mconfig, "PythonAuthzHandler", val);
}
static const char *directive_PythonCleanupHandler(cmd_parms *cmd, void * mconfig,
const char *val) {
return python_directive(cmd, mconfig, "PythonCleanupHandler", val);
}
static const char *directive_PythonFixupHandler(cmd_parms *cmd, void * mconfig,
const char *val) {
return python_directive(cmd, mconfig, "PythonFixupHandler", val);
Expand Down Expand Up @@ -3349,6 +3529,7 @@ static int PythonHandler(request_rec *req) {
static int PythonHeaderParserHandler(request_rec *req) {
int rc;

/* run PythonInitHandler, if not already */
if (! ap_table_get(req->notes, "python_init_ran")) {
rc = python_handler(req, "PythonInitHandler");
if ((rc != OK) && (rc != DECLINED))
Expand All @@ -3362,6 +3543,11 @@ static int PythonLogHandler(request_rec *req) {
static int PythonPostReadRequestHandler(request_rec *req) {
int rc;

/* register the clean up directive handler */
ap_register_cleanup(req->pool, (void *)req, python_cleanup_handler,
ap_null_cleanup);

/* run PythonInitHandler */
rc = python_handler(req, "PythonInitHandler");
ap_table_set(req->notes, "python_init_ran", "1");
if ((rc != OK) && (rc != DECLINED))
Expand Down Expand Up @@ -3419,7 +3605,15 @@ command_rec python_commands[] =
NULL,
OR_ALL,
RAW_ARGS,
"Python authorization (user allowed _here_) handlers."
"Python authorization handlers."
},
{
"PythonCleanupHandler",
directive_PythonCleanupHandler,
NULL,
OR_ALL,
RAW_ARGS,
"Python clean up handlers."
},
{
"PythonDebug",
Expand Down

0 comments on commit 124eec7

Please sign in to comment.