[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

can we upload mod-wsgi 2.5-1~lenny1 to stable?



Hi release team,

Debian Lenny was shipped with mod-wsgi v2.3. Upstream released two new
bug fix versions since then - 2.4 and 2.5 (with bug fixes mostly
backported from developement branch - 3.x). Since upstream changelog
mentions[1] also new features (also backported from 3.x), we (Bernd and I)
contacted upstream (who helped us a lot before) about these new features
and he told us that these features are actually a bug fixes as well
and he recommends not to strip them in an upload to Debian stable.

What do you think? Can we upload 2.5 to Debian stable?

Please note that I use (in place where I work) mod-wsgi 2.5 in
production since May and one of Debian servers (the one that hosts
wiki.debian.org) is using backported version as well.

I'm attaching the output of:

 debdiff mod-wsgi_2.3-1.dsc mod-wsgi_2.5-1~lenny1.dsc | filterdiff -x \*configure

diffstat:

 README                                         |    2 
 configure                                      | 2391 ++++++++++---------------
 configure.ac                                   |  105 -
 debian/README.source                           |    6 
 debian/changelog                               |   26 
 debian/control                                 |    4 
 debian/copyright                               |    4 
 debian/libapache2-mod-wsgi.postrm              |    1 
 debian/patches/configure-apache-version.dpatch |   27 
 mod_wsgi.c                                     |  412 +++-
 10 files changed, 1426 insertions(+), 1552 deletions(-)

[1] http://code.google.com/p/modwsgi/wiki/ChangesInVersion0204
    http://code.google.com/p/modwsgi/wiki/ChangesInVersion0205
-- 
-=[     Piotr Ożarowski     ]=-
-=[ http://www.ozarowski.pl ]=-
diff -Nru mod-wsgi-2.3/configure mod-wsgi-2.5/configure
diff -Nru mod-wsgi-2.3/configure.ac mod-wsgi-2.5/configure.ac
--- mod-wsgi-2.3/configure.ac	2008-01-24 11:19:14.000000000 +0100
+++ mod-wsgi-2.5/configure.ac	2009-04-15 01:06:28.000000000 +0200
@@ -1,6 +1,6 @@
 dnl  vim: set sw=4 expandtab :
 dnl
-dnl  Copyright 2007-2008 GRAHAM DUMPLETON
+dnl  Copyright 2007-2009 GRAHAM DUMPLETON
 dnl 
 dnl  Licensed under the Apache License, Version 2.0 (the "License");
 dnl  you may not use this file except in compliance with the License.
@@ -50,15 +50,18 @@
 
 AC_SUBST(PYTHON)
 
-PYTHON_VERSION=`${PYTHON} -c 'from distutils import sysconfig; \
-    print sysconfig.get_config_var("VERSION")'`
-
-CPPFLAGS1=`${PYTHON} -c 'from distutils import sysconfig; \
-    print "-I" + sysconfig.get_config_var("INCLUDEPY")'`
-
-CPPFLAGS2=`${PYTHON} -c 'from distutils import sysconfig; \
-    print " ".join(filter(lambda x: x.startswith("-D"), \
-    sysconfig.get_config_var("CFLAGS").split()))'`
+PYTHON_VERSION=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write((sysconfig.get_config_var("VERSION")))'`
+
+CPPFLAGS1=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write("-I" + sysconfig.get_config_var("INCLUDEPY"))'`
+
+CPPFLAGS2=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write(" ".join(filter(lambda x: x.startswith("-D"), \
+    sysconfig.get_config_var("CFLAGS").split())))'`
 
 if test "${ENABLE_EMBEDDED}" != "yes"; then
 CPPFLAGS3="-DMOD_WSGI_DISABLE_EMBEDDED"
@@ -66,40 +69,63 @@
 CPPFLAGS3=""
 fi
 
-CPPFLAGS="${CPPFLAGS1} ${CPPFLAGS2} ${CPPFLAGS3}"
+CPPFLAGS="${CPPFLAGS} ${CPPFLAGS1} ${CPPFLAGS2} ${CPPFLAGS3}"
 
 AC_SUBST(CPPFLAGS)
 
-PYTHONFRAMEWORKDIR=`${PYTHON} -c 'from distutils import sysconfig; \
-    print sysconfig.get_config_var("PYTHONFRAMEWORKDIR")'`
-PYTHONFRAMEWORKPREFIX=`${PYTHON} -c 'from distutils import sysconfig; \
-    print sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX")'`
-PYTHONFRAMEWORK=`${PYTHON} -c 'from distutils import sysconfig; \
-    print sysconfig.get_config_var("PYTHONFRAMEWORK")'`
+PYTHONLIBDIR=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write(sysconfig.get_config_var("LIBDIR"))'`
+PYTHONCFGDIR=`${PYTHON} -c 'from sys import stdout; \
+    import distutils.sysconfig; \
+    stdout.write(distutils.sysconfig.get_python_lib(plat_specific=1, \
+    standard_lib=1) +"/config")'`
+PYTHONFRAMEWORKDIR=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write(sysconfig.get_config_var("PYTHONFRAMEWORKDIR"))'`
+PYTHONFRAMEWORKPREFIX=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write(sysconfig.get_config_var("PYTHONFRAMEWORKPREFIX"))'`
+PYTHONFRAMEWORK=`${PYTHON} -c 'from sys import stdout; \
+    from distutils import sysconfig; \
+    stdout.write(sysconfig.get_config_var("PYTHONFRAMEWORK"))'`
 
 if test "${PYTHONFRAMEWORKDIR}" = "no-framework"; then
-    LDFLAGS=`${PYTHON} -c 'import distutils.sysconfig; \
-        print "-L" + distutils.sysconfig.get_python_lib(plat_specific=1, \
-        standard_lib=1) +"/config"'`
+    LDFLAGS1="-L${PYTHONLIBDIR}"
+    LDFLAGS2="-L${PYTHONCFGDIR}"
 
     LDLIBS1="-lpython${PYTHON_VERSION}"
-    LDLIBS2=`${PYTHON} -c 'from distutils import sysconfig; \
-        print sysconfig.get_config_var("LIBS")'`
-
-    LDLIBS="${LDLIBS1} ${LDLIBS2}"
+    LDLIBS2=`${PYTHON} -c 'from sys import stdout; \
+        from distutils import sysconfig; \
+        stdout.write(sysconfig.get_config_var("LIBS"))'`
+    LDLIBS3=`${PYTHON} -c 'from sys import stdout; \
+        from distutils import sysconfig; \
+        stdout.write(sysconfig.get_config_var("SYSLIBS"))'`
 else
-    LDFLAGS1="-Wl,-F${PYTHONFRAMEWORKPREFIX} -framework ${PYTHONFRAMEWORK}"
-
-    VERSION="${PYTHON_VERSION}"
-    STRING="${PYTHONFRAMEWORKDIR}/Versions/${VERSION}/${PYTHONFRAMEWORK}"
-    LDFLAGS2=`${PYTHON} -c "from distutils import sysconfig; \
-        print sysconfig.get_config_var(\"LINKFORSHARED\").replace( \
-        \"${STRING}\", '')"`
+    if test -f "${PYTHONCFGDIR}/libpython${PYTHON_VERSION}.a"; then
+        LDFLAGS2="-L${PYTHONCFGDIR}"
 
-    LDFLAGS="${LDFLAGS1} ${LDFLAGS2}"
-
-    LDLIBS=`${PYTHON} -c 'from distutils import sysconfig; \
-        print sysconfig.get_config_var("LIBS")'`
+        LDLIBS1="-lpython${PYTHON_VERSION}"
+        LDLIBS2=`${PYTHON} -c 'from sys import stdout; \
+            from distutils import sysconfig; \
+            stdout.write(sysconfig.get_config_var("LIBS"))'`
+        LDLIBS3=`${PYTHON} -c 'from sys import stdout; \
+            from distutils import sysconfig; \
+            stdout.write(sysconfig.get_config_var("SYSLIBS"))'`
+    else
+        LDFLAGS1="-F${PYTHONFRAMEWORKPREFIX} -framework ${PYTHONFRAMEWORK}"
+
+        VERSION="${PYTHON_VERSION}"
+        STRING="${PYTHONFRAMEWORKDIR}/Versions/${VERSION}/${PYTHONFRAMEWORK}"
+        LDFLAGS2=`${PYTHON} -c "from sys import stdout; \
+            from distutils import sysconfig; \
+            stdout.write(sysconfig.get_config_var(
+            \"LINKFORSHARED\").replace(\"${STRING}\", ''))"`
+
+        LDLIBS1=`${PYTHON} -c 'from sys import stdout; \
+            from distutils import sysconfig; \
+            stdout.write(sysconfig.get_config_var("LIBS"))'`
+    fi
 fi
 
 CFLAGS=""
@@ -110,9 +136,16 @@
         CFLAGS="${CFLAGS} -Wc,'-arch ${ARCH}'" 
         LDFLAGS3="${LDFLAGS3} -arch ${ARCH}" 
     done
-    LDFLAGS="${LDFLAGS3} ${LDFLAGS}"
 fi
 
+LDFLAGS="${LDFLAGS} ${LDFLAGS1} ${LDFLAGS2} ${LDFLAGS3}"
+LDLIBS="${LDLIBS} ${LDLIBS1} ${LDLIBS2} ${LDLIBS3}"
+
+#LDFLAGS=`echo ${LDFLAGS} | \
+# sed -e "s/-Wl,\([[^ ]][[^ ]]*\)/\1/g" -e "s/\([[^ ]][[^ ]]*\)/-Wl,\1/g"`
+#LDLIBS=`echo ${LDLIBS} | \
+# sed -e "s/-Wl,\([[^ ]][[^ ]]*\)/\1/g" -e "s/\([[^ ]][[^ ]]*\)/-Wl,\1/g"`
+
 AC_SUBST(CFLAGS)
 AC_SUBST(LDFLAGS)
 AC_SUBST(LDLIBS)
diff -Nru mod-wsgi-2.3/debian/changelog mod-wsgi-2.5/debian/changelog
--- mod-wsgi-2.3/debian/changelog	2009-08-08 13:19:06.000000000 +0200
+++ mod-wsgi-2.5/debian/changelog	2009-08-08 13:19:06.000000000 +0200
@@ -1,3 +1,29 @@
+mod-wsgi (2.5-1~lenny1) stable; urgency=low
+
+  * Rebuild for Lenny (Closes: #526154)
+
+ -- Piotr Ożarowski <piotr@debian.org>  Sat, 08 Aug 2009 12:59:21 +0200
+
+mod-wsgi (2.5-1) unstable; urgency=low
+
+  * New upstream bugfix release.
+  * Updating patches to suit the new version. 
+
+ -- Bernd Zeimetz <bzed@debian.org>  Sun, 17 May 2009 01:17:56 +0200
+
+mod-wsgi (2.4-1) unstable; urgency=low
+
+  [ Sandro Tosi ]
+  * Switch Vcs-Browser field to viewsvn
+
+  [ Piotr Ożarowski ]
+  * New upstream release
+  * Don't ignore errors in postrm maintainer script
+  * Standards-Version bumped to 3.8.1
+    + add debian/README.source file
+
+ -- Piotr Ożarowski <piotr@debian.org>  Sat, 18 Apr 2009 22:06:03 +0200
+
 mod-wsgi (2.3-1) unstable; urgency=low
 
   * New upstream release (Closes: #496067). This upload covers the changes of
diff -Nru mod-wsgi-2.3/debian/control mod-wsgi-2.5/debian/control
--- mod-wsgi-2.3/debian/control	2009-08-08 13:19:06.000000000 +0200
+++ mod-wsgi-2.5/debian/control	2009-08-08 13:19:06.000000000 +0200
@@ -5,9 +5,9 @@
 Uploaders: Bernd Zeimetz <bzed@debian.org>, Piotr Ożarowski <piotr@debian.org>
 Build-Depends: debhelper (>= 5), python-all-dev, apache2-threaded-dev, dpatch
 Homepage: http://www.modwsgi.org/
-Standards-Version: 3.7.3
+Standards-Version: 3.8.1
 Vcs-Svn: svn://svn.debian.org/python-modules/packages/mod-wsgi/trunk/
-Vcs-Browser: http://svn.debian.org/wsvn/python-modules/packages/mod-wsgi/trunk/?op=log
+Vcs-Browser: http://svn.debian.org/viewsvn/python-modules/packages/mod-wsgi/trunk/
 
 Package: libapache2-mod-wsgi
 Architecture: any
diff -Nru mod-wsgi-2.3/debian/copyright mod-wsgi-2.5/debian/copyright
--- mod-wsgi-2.3/debian/copyright	2009-08-08 13:19:06.000000000 +0200
+++ mod-wsgi-2.5/debian/copyright	2009-08-08 13:19:06.000000000 +0200
@@ -9,7 +9,7 @@
 
 Copyright: 
 
-    Copyright 2007 GRAHAM DUMPLETON
+    Copyright 2007-2009 GRAHAM DUMPLETON
 
 License:
 
@@ -28,5 +28,5 @@
 On Debian systems the full text of the Apache License, Version 2,
 can be found in `/usr/share/common-licenses/Apache-2.0'.
 
-The Debian packaging is (C) 2007-2008, Bernd Zeimetz <bernd@bzed.de> and
+The Debian packaging is © 2007-2009, Bernd Zeimetz <bernd@bzed.de> and
 is licensed under the Apache License, Version 2.0, see below.
diff -Nru mod-wsgi-2.3/debian/libapache2-mod-wsgi.postrm mod-wsgi-2.5/debian/libapache2-mod-wsgi.postrm
--- mod-wsgi-2.3/debian/libapache2-mod-wsgi.postrm	2009-08-08 13:19:06.000000000 +0200
+++ mod-wsgi-2.5/debian/libapache2-mod-wsgi.postrm	2009-08-08 13:19:06.000000000 +0200
@@ -1,4 +1,5 @@
 #! /bin/sh
+set -e
 
 if [ "$1" = "purge" -o "$1" = "remove" ]; then
     # remove pseudo conffile
diff -Nru mod-wsgi-2.3/debian/patches/configure-apache-version.dpatch mod-wsgi-2.5/debian/patches/configure-apache-version.dpatch
--- mod-wsgi-2.3/debian/patches/configure-apache-version.dpatch	2009-08-08 13:19:06.000000000 +0200
+++ mod-wsgi-2.5/debian/patches/configure-apache-version.dpatch	2009-08-08 13:19:06.000000000 +0200
@@ -4,24 +4,27 @@
 ## DP: we don't want to build-depend on Apache2 to build the package.
 
 @DPATCH@
-diff -urNad mod-wsgi-experimental~/configure mod-wsgi-experimental/configure
---- mod-wsgi-experimental~/configure	2007-12-13 11:26:59.000000000 +0100
-+++ mod-wsgi-experimental/configure	2007-12-14 21:04:52.000000000 +0100
-@@ -1677,13 +1677,6 @@
+diff -urNad mod-wsgi~/configure mod-wsgi/configure
+--- mod-wsgi~/configure	2009-04-15 01:06:28.000000000 +0200
++++ mod-wsgi/configure	2009-05-17 01:15:27.000000000 +0200
+@@ -1291,16 +1291,6 @@
  
+ fi
  
- 
--{ echo "$as_me:$LINENO: checking Apache version" >&5
--echo $ECHO_N "checking Apache version... $ECHO_C" >&6; }
+-
+-
+-echo "$as_me:$LINENO: checking Apache version" >&5
+-echo $ECHO_N "checking Apache version... $ECHO_C" >&6
 -HTTPD="`${APXS} -q SBINDIR`/`${APXS} -q TARGET`"
 -HTTPD_VERSION=`$HTTPD -v | awk '/version/ {print $3}' | awk -F/ '{print $2}'`
--{ echo "$as_me:$LINENO: result: $HTTPD_VERSION" >&5
--echo "${ECHO_T}$HTTPD_VERSION" >&6; }
+-echo "$as_me:$LINENO: result: $HTTPD_VERSION" >&5
+-echo "${ECHO_T}$HTTPD_VERSION" >&6
 -
- 
- # Check whether --with-python was given.
+-
+ # Check whether --with-python or --without-python was given.
  if test "${with_python+set}" = set; then
-@@ -1807,7 +1800,7 @@
+   withval="$with_python"
+@@ -1461,7 +1451,7 @@
  LIBEXECDIR="`${APXS} -q LIBEXECDIR`"
  
  
diff -Nru mod-wsgi-2.3/debian/README.source mod-wsgi-2.5/debian/README.source
--- mod-wsgi-2.3/debian/README.source	1970-01-01 01:00:00.000000000 +0100
+++ mod-wsgi-2.5/debian/README.source	2009-08-08 13:19:06.000000000 +0200
@@ -0,0 +1,6 @@
+This package is using dpatch patch system. 
+
+To get the fully patched source after unpacking the source package, cd to
+the root level of the source package and run `./debian/rules patch`
+
+See /usr/share/doc/dpatch/README.source.gz for more information.
diff -Nru mod-wsgi-2.3/mod_wsgi.c mod-wsgi-2.5/mod_wsgi.c
--- mod-wsgi-2.3/mod_wsgi.c	2008-08-23 15:28:00.000000000 +0200
+++ mod-wsgi-2.5/mod_wsgi.c	2009-05-11 13:15:20.000000000 +0200
@@ -1,7 +1,7 @@
 /* vim: set sw=4 expandtab : */
 
 /*
- * Copyright 2007-2008 GRAHAM DUMPLETON
+ * Copyright 2007-2009 GRAHAM DUMPLETON
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -245,8 +245,8 @@
 /* Version and module information. */
 
 #define MOD_WSGI_MAJORVERSION_NUMBER 2
-#define MOD_WSGI_MINORVERSION_NUMBER 2
-#define MOD_WSGI_VERSION_STRING "2.3"
+#define MOD_WSGI_MINORVERSION_NUMBER 5
+#define MOD_WSGI_VERSION_STRING "2.5"
 
 #if AP_SERVER_MAJORVERSION_NUMBER < 2
 module MODULE_VAR_EXPORT wsgi_module;
@@ -1055,6 +1055,20 @@
     PyObject_Del(self);
 }
 
+static PyObject *Log_close(LogObject *self, PyObject *args)
+{
+    if (self->expired) {
+        PyErr_SetString(PyExc_RuntimeError, "log object has expired");
+        return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, ":close"))
+        return NULL;
+
+    PyErr_SetString(PyExc_RuntimeError, "log object cannot be closed");
+    return NULL;
+}
+
 static PyObject *Log_flush(LogObject *self, PyObject *args)
 {
     if (self->expired) {
@@ -1247,13 +1261,25 @@
     return Py_None;
 }
 
+static PyObject *Log_closed(LogObject *self, void *closure)
+{
+    Py_INCREF(Py_False);
+    return Py_False;
+}
+
 static PyMethodDef Log_methods[] = {
-    { "flush",      (PyCFunction)Log_flush,      METH_VARARGS, 0},
-    { "write",      (PyCFunction)Log_write,      METH_VARARGS, 0},
-    { "writelines", (PyCFunction)Log_writelines, METH_VARARGS, 0},
+    { "close",      (PyCFunction)Log_close,      METH_VARARGS, 0 },
+    { "flush",      (PyCFunction)Log_flush,      METH_VARARGS, 0 },
+    { "write",      (PyCFunction)Log_write,      METH_VARARGS, 0 },
+    { "writelines", (PyCFunction)Log_writelines, METH_VARARGS, 0 },
     { NULL, NULL}
 };
 
+static PyGetSetDef Log_getset[] = {
+    { "closed", (getter)Log_closed, NULL, 0 },
+    { NULL },
+};
+
 static PyTypeObject Log_Type = {
     /* The ob_type field must be initialized in the module init function
      * to be portable to Windows without using C++. */
@@ -1288,7 +1314,7 @@
     0,                      /*tp_iternext*/
     Log_methods,            /*tp_methods*/
     0,                      /*tp_members*/
-    0,                      /*tp_getset*/
+    Log_getset,             /*tp_getset*/
     0,                      /*tp_base*/
     0,                      /*tp_dict*/
     0,                      /*tp_descr_get*/
@@ -1684,14 +1710,16 @@
          */
 
         while (!self->done) {
-            /* Increase the size of the string by 25%. */
+            if (length == size) {
+                /* Increase the size of the string by 25%. */
 
-            size = size + (size >> 2);
+                size = size + (size >> 2);
 
-            if (_PyString_Resize(&result, size))
-                return NULL;
+                if (_PyString_Resize(&result, size))
+                    return NULL;
 
-            buffer = PyString_AS_STRING((PyStringObject *)result);
+                buffer = PyString_AS_STRING((PyStringObject *)result);
+            }
 
             /* Now make succesive attempt at reading data. */
 
@@ -1992,7 +2020,7 @@
                     memcpy(self->buffer, p, self->size);
                 }
 
-                if (buffer[length-1] != '\n') {
+                if (buffer[length-1] != '\n' && length == size) {
                     /* Increase size of string and keep going. */
 
                     size = size + (size >> 2);
@@ -2082,10 +2110,10 @@
 }
 
 static PyMethodDef Input_methods[] = {
-    { "close",     (PyCFunction)Input_close,     METH_VARARGS, 0},
-    { "read",      (PyCFunction)Input_read,      METH_VARARGS, 0},
-    { "readline",  (PyCFunction)Input_readline,  METH_VARARGS, 0},
-    { "readlines", (PyCFunction)Input_readlines, METH_VARARGS, 0},
+    { "close",     (PyCFunction)Input_close,     METH_VARARGS, 0 },
+    { "read",      (PyCFunction)Input_read,      METH_VARARGS, 0 },
+    { "readline",  (PyCFunction)Input_readline,  METH_VARARGS, 0 },
+    { "readlines", (PyCFunction)Input_readlines, METH_VARARGS, 0 },
     { NULL, NULL}
 };
 
@@ -2422,6 +2450,13 @@
                 return 0;
             }
 
+            if (strchr(name, '\n') != 0 || strchr(value, '\n') != 0) {
+                PyErr_Format(PyExc_ValueError, "embedded newline in "
+                             "response header with name '%s' and value '%s'",
+                             name, value);
+                return 0;
+            }
+
             if (!strcasecmp(name, "Content-Type")) {
 #if AP_SERVER_MAJORVERSION_NUMBER < 2
                 r->content_type = apr_pstrdup(r->pool, value);
@@ -2685,6 +2720,9 @@
 
     APR_BRIGADE_INSERT_TAIL(bb, b);
 
+    b = apr_bucket_flush_create(r->connection->bucket_alloc);
+    APR_BRIGADE_INSERT_TAIL(bb, b);
+
     b = apr_bucket_eos_create(r->connection->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, b);
 
@@ -2801,6 +2839,13 @@
     PyDict_SetItemString(vars, "wsgi.file_wrapper", object);
     Py_DECREF(object);
 
+    /* Add mod_wsgi version information. */
+
+    object = Py_BuildValue("(ii)", MOD_WSGI_MAJORVERSION_NUMBER,
+                           MOD_WSGI_MINORVERSION_NUMBER);
+    PyDict_SetItemString(vars, "mod_wsgi.version", object);
+    Py_DECREF(object);
+
     /*
      * If Apache extensions are enabled and running in embedded
      * mode add a CObject reference to the Apache request_rec
@@ -3205,9 +3250,9 @@
 }
 
 static PyMethodDef Adapter_methods[] = {
-    { "start_response", (PyCFunction)Adapter_start_response, METH_VARARGS, 0},
-    { "write",          (PyCFunction)Adapter_write, METH_VARARGS, 0},
-    { "file_wrapper",   (PyCFunction)Adapter_file_wrapper, METH_VARARGS, 0},
+    { "start_response", (PyCFunction)Adapter_start_response, METH_VARARGS, 0 },
+    { "write",          (PyCFunction)Adapter_write, METH_VARARGS, 0 },
+    { "file_wrapper",   (PyCFunction)Adapter_file_wrapper, METH_VARARGS, 0 },
     { NULL, NULL}
 };
 
@@ -3366,7 +3411,7 @@
 }
 
 static PyMethodDef Stream_methods[] = {
-    { "close",      (PyCFunction)Stream_close,      METH_VARARGS, 0},
+    { "close",      (PyCFunction)Stream_close,      METH_VARARGS, 0 },
     { NULL, NULL}
 };
 
@@ -3538,7 +3583,7 @@
         }
     }
 
-    Py_INCREF(m);
+    Py_XDECREF(m);
 
     Py_INCREF(h);
 
@@ -3698,6 +3743,71 @@
     }
 
     /*
+     * If running in daemon process, override as appropriate
+     * the USER, USERNAME or LOGNAME environment  variables
+     * so that they match the user that the process is running
+     * as. Need to do this else we inherit the value from the
+     * Apache parent process which is likely wrong as will be
+     * root or the user than ran sudo when Apache started.
+     * Can't update these for normal Apache child processes
+     * as that would change the expected environment of other
+     * Apache modules.
+     */
+
+#ifndef WIN32
+    if (wsgi_daemon_pool) {
+        module = PyImport_ImportModule("os");
+
+        if (module) {
+            PyObject *dict = NULL;
+            PyObject *key = NULL;
+            PyObject *value = NULL;
+
+            dict = PyModule_GetDict(module);
+            object = PyDict_GetItemString(dict, "environ");
+
+            if (object) {
+                struct passwd *pwent;
+
+                pwent = getpwuid(geteuid());
+
+                if (getenv("USER")) {
+                    key = PyString_FromString("USER");
+                    value = PyString_FromString(pwent->pw_name);
+
+                    PyObject_SetItem(object, key, value);
+
+                    Py_DECREF(key);
+                    Py_DECREF(value);
+                }
+
+                if (getenv("USERNAME")) {
+                    key = PyString_FromString("USERNAME");
+                    value = PyString_FromString(pwent->pw_name);
+
+                    PyObject_SetItem(object, key, value);
+
+                    Py_DECREF(key);
+                    Py_DECREF(value);
+                }
+
+                if (getenv("LOGNAME")) {
+                    key = PyString_FromString("LOGNAME");
+                    value = PyString_FromString(pwent->pw_name);
+
+                    PyObject_SetItem(object, key, value);
+
+                    Py_DECREF(key);
+                    Py_DECREF(value);
+                }
+            }
+
+            Py_DECREF(module);
+        }
+    }
+#endif
+
+    /*
      * If running in daemon process, override HOME environment
      * variable so that is matches the home directory of the
      * user that the process is running as. Need to do this as
@@ -3779,18 +3889,40 @@
      * added using site.addsitedir() so that any Python .pth
      * files are opened and additional directories so defined
      * are added to default Python search path as well. This
-     * allows virtual Python environments to work.
+     * allows virtual Python environments to work. Note that
+     * site.addsitedir() adds new directories at the end of
+     * sys.path when they really need to be added in order at
+     * the start. We therefore need to do a fiddle and shift
+     * any newly added directories to the start of sys.path.
      */
 
     if (!wsgi_daemon_pool)
         wsgi_python_path = wsgi_server_config->python_path;
 
     if (wsgi_python_path) {
+        PyObject *path = NULL;
+
         module = PyImport_ImportModule("site");
+        path = PySys_GetObject("path");
 
-        if (module) {
+        if (module && path) {
             PyObject *dict = NULL;
 
+            PyObject *old = NULL;
+            PyObject *new = NULL;
+            PyObject *tmp = NULL;
+
+            PyObject *item = NULL;
+
+            int i = 0;
+
+            old = PyList_New(0);
+            new = PyList_New(0);
+            tmp = PyList_New(0);
+
+            for (i=0; i<PyList_Size(path); i++)
+                PyList_Append(old, PyList_GetItem(path, i));
+
             dict = PyModule_GetDict(module);
             object = PyDict_GetItemString(dict, "addsitedir");
 
@@ -3903,14 +4035,43 @@
                 Py_END_ALLOW_THREADS
             }
 
+            for (i=0; i<PyList_Size(path); i++)
+                PyList_Append(tmp, PyList_GetItem(path, i));
+
+            for (i=0; i<PyList_Size(tmp); i++) {
+                item = PyList_GetItem(tmp, i);
+                if (!PySequence_Contains(old, item)) {
+                    int index = PySequence_Index(path, item);
+                    PyList_Append(new, item);
+                    if (index != -1)
+                        PySequence_DelItem(path, index); 
+                }
+            }
+
+            PyList_SetSlice(path, 0, 0, new);
+
+            Py_DECREF(old);
+            Py_DECREF(new);
+            Py_DECREF(tmp);
+
             Py_DECREF(module);
         }
         else {
-            Py_BEGIN_ALLOW_THREADS
-            ap_log_error(APLOG_MARK, WSGI_LOG_ERR(0), wsgi_server,
-                         "mod_wsgi (pid=%d): Unable to import 'site' "
-                         "module.", getpid());
-            Py_END_ALLOW_THREADS
+            if (!module) {
+                Py_BEGIN_ALLOW_THREADS
+                ap_log_error(APLOG_MARK, WSGI_LOG_ERR(0), wsgi_server,
+                             "mod_wsgi (pid=%d): Unable to import 'site' "
+                             "module.", getpid());
+                Py_END_ALLOW_THREADS
+            }
+
+            if (!path) {
+                Py_BEGIN_ALLOW_THREADS
+                ap_log_error(APLOG_MARK, WSGI_LOG_ERR(0), wsgi_server,
+                             "mod_wsgi (pid=%d): Lookup for 'sys.path' "
+                             "failed.", getpid());
+                Py_END_ALLOW_THREADS
+            }
         }
     }
 
@@ -3962,6 +4123,16 @@
                        MOD_WSGI_MAJORVERSION_NUMBER,
                        MOD_WSGI_MINORVERSION_NUMBER));
 
+    /*
+     * Add information about process group and application
+     * group to the Python 'mod_wsgi' module.
+     */
+
+    PyModule_AddObject(module, "process_group",
+                       PyString_FromString(wsgi_daemon_group));
+    PyModule_AddObject(module, "application_group",
+                       PyString_FromString(name));
+
     Py_DECREF(module);
 
     /*
@@ -4204,7 +4375,7 @@
 
                 Py_XDECREF(result);
 
-                Py_DECREF(m);
+                Py_XDECREF(m);
             }
 
             Py_XDECREF(res);
@@ -4313,7 +4484,7 @@
 
             Py_XDECREF(result);
 
-            Py_DECREF(m);
+            Py_XDECREF(m);
         }
 
         Py_XDECREF(res);
@@ -4420,7 +4591,7 @@
     }
 }
 
-static apr_status_t wsgi_python_term(void *data)
+static apr_status_t wsgi_python_term()
 {
     PyInterpreterState *interp = NULL;
     PyThreadState *tstate = NULL;
@@ -4448,6 +4619,30 @@
     return APR_SUCCESS;
 }
 
+#if AP_SERVER_MAJORVERSION_NUMBER < 2
+static void wsgi_python_parent_cleanup(void *data)
+#else
+static apr_status_t wsgi_python_parent_cleanup(void *data)
+#endif
+{
+    if (wsgi_parent_pid == getpid()) {
+        /*
+	 * Destroy Python itself including the main
+	 * interpreter. If mod_python is being loaded it
+	 * is left to mod_python to destroy Python,
+	 * although it currently doesn't do so.
+         */
+
+        if (wsgi_python_initialized)
+            wsgi_python_term();
+    }
+
+#if AP_SERVER_MAJORVERSION_NUMBER >= 2
+    return APR_SUCCESS;
+#endif
+}
+
+
 static void wsgi_python_init(apr_pool_t *p)
 {
 #if defined(DARWIN) && (AP_SERVER_MAJORVERSION_NUMBER < 2)
@@ -4483,7 +4678,7 @@
         /* Initialise Python. */
 
         ap_log_error(APLOG_MARK, WSGI_LOG_INFO(0), wsgi_server,
-                     "mod_wsgi: Initializing Python.");
+                     "mod_wsgi (pid=%d): Initializing Python.", getpid());
 
         initialized = 1;
 
@@ -4513,6 +4708,19 @@
         PyEval_ReleaseLock();
 
         wsgi_python_initialized = 1;
+
+    /*
+     * Register cleanups to be performed on parent restart
+     * or shutdown. This will destroy Python itself.
+     */
+
+#if AP_SERVER_MAJORVERSION_NUMBER < 2
+        ap_register_cleanup(p, NULL, wsgi_python_parent_cleanup,
+                            ap_null_cleanup);
+#else
+        apr_pool_cleanup_register(p, NULL, wsgi_python_parent_cleanup,
+                                  apr_pool_cleanup_null);
+#endif
     }
 }
 
@@ -4753,7 +4961,7 @@
             }
 #else
             apr_finfo_t finfo;
-            if (apr_stat(&finfo, filename, APR_FINFO_SIZE,
+            if (apr_stat(&finfo, filename, APR_FINFO_NORM,
                          pool) != APR_SUCCESS) {
                 object = PyLong_FromLongLong(0);
             }
@@ -4819,7 +5027,7 @@
             }
 #else
             apr_finfo_t finfo;
-            if (apr_stat(&finfo, filename, APR_FINFO_SIZE,
+            if (apr_stat(&finfo, filename, APR_FINFO_NORM,
                          pool) != APR_SUCCESS) {
                 return 1;
             }
@@ -5164,7 +5372,7 @@
 }
 
 /*
- * Apache child process initialision and cleanup. Initialise
+ * Apache child process initialisation and cleanup. Initialise
  * global table containing Python interpreter instances and
  * cache reference to main interpreter. Also register cleanup
  * function to delete interpreter on process shutdown.
@@ -5224,11 +5432,11 @@
     /*
      * Destroy Python itself including the main interpreter.
      * If mod_python is being loaded it is left to mod_python to
-     * destroy mod_python, although it currently doesn't do so.
+     * destroy Python, although it currently doesn't do so.
      */
 
     if (wsgi_python_initialized)
-        wsgi_python_term(0);
+        wsgi_python_term();
 
 #if AP_SERVER_MAJORVERSION_NUMBER >= 2
     return APR_SUCCESS;
@@ -5412,6 +5620,9 @@
                                               entry->handler_script,
                                               entry->process_group,
                                               entry->application_group);
+
+                    if (PyErr_Occurred()) 
+                        PyErr_Clear(); 
                 }
 
                 /* Safe now to release the module lock. */
@@ -5655,7 +5866,7 @@
     while (*args) {
         char const *option;
 
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (!strcmp(option, "%{GLOBAL}"))
             option = "";
@@ -5744,7 +5955,7 @@
 
     object = (WSGIScriptFile *)apr_array_push(sconfig->import_list);
 
-    object->handler_script = ap_getword_conf(cmd->temp_pool, &args);
+    object->handler_script = ap_getword_conf(cmd->pool, &args);
     object->process_group = NULL;
     object->application_group = NULL;
 
@@ -5752,7 +5963,7 @@
         return "Location of import script not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "application-group=") == option) {
             value = option + 18;
@@ -5803,13 +6014,13 @@
 
     object = newWSGIScriptFile(cmd->pool);
 
-    object->handler_script = ap_getword_conf(cmd->temp_pool, &args);
+    object->handler_script = ap_getword_conf(cmd->pool, &args);
 
     if (!object->handler_script || !*object->handler_script)
         return "Location of dispatch script not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "application-group=") == option) {
             value = option + 18;
@@ -5972,13 +6183,13 @@
 
     object = newWSGIScriptFile(cmd->pool);
 
-    object->handler_script = ap_getword_conf(cmd->temp_pool, &args);
+    object->handler_script = ap_getword_conf(cmd->pool, &args);
 
     if (!object->handler_script || !*object->handler_script)
         return "Location of access script not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "application-group=") == option) {
             value = option + 18;
@@ -6008,13 +6219,13 @@
 
     object = newWSGIScriptFile(cmd->pool);
 
-    object->handler_script = ap_getword_conf(cmd->temp_pool, &args);
+    object->handler_script = ap_getword_conf(cmd->pool, &args);
 
     if (!object->handler_script || !*object->handler_script)
         return "Location of auth user script not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "application-group=") == option) {
             value = option + 18;
@@ -6044,13 +6255,13 @@
 
     object = newWSGIScriptFile(cmd->pool);
 
-    object->handler_script = ap_getword_conf(cmd->temp_pool, &args);
+    object->handler_script = ap_getword_conf(cmd->pool, &args);
 
     if (!object->handler_script || !*object->handler_script)
         return "Location of auth group script not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "application-group=") == option) {
             value = option + 18;
@@ -6226,9 +6437,8 @@
         n = r->filename;
 
     message = apr_psprintf(r->pool, "%s: %s", e, n);
-    apr_table_set(r->notes, "error-notes", message);
 
-    ap_log_rerror(APLOG_MARK, WSGI_LOG_ERR(0), r, message);
+    ap_log_rerror(APLOG_MARK, WSGI_LOG_ERR(0), r, "%s", message);
 }
 
 static void wsgi_build_environment(request_rec *r)
@@ -7308,13 +7518,13 @@
 
     /* Now parse options for directive. */
 
-    name = ap_getword_conf(cmd->temp_pool, &args);
+    name = ap_getword_conf(cmd->pool, &args);
 
     if (!name || !*name)
         return "Name of WSGI daemon process not supplied.";
 
     while (*args) {
-        option = ap_getword_conf(cmd->temp_pool, &args);
+        option = ap_getword_conf(cmd->pool, &args);
 
         if (strstr(option, "user=") == option) {
             value = option + 5;
@@ -7617,20 +7827,17 @@
     return NULL;
 }
 
-static void wsgi_signal_handler(int signum)
-{
-    wsgi_daemon_shutdown++;
-}
+static apr_file_t *wsgi_signal_pipe_in = NULL;
+static apr_file_t *wsgi_signal_pipe_out = NULL;
 
-static int wsgi_check_signal(int signum)
+static void wsgi_signal_handler(int signum)
 {
-    if (signum == SIGINT || signum == SIGTERM) {
-        wsgi_daemon_shutdown++;
+    apr_size_t nbytes = 1;
 
-        return 1;
-    }
+    apr_file_write(wsgi_signal_pipe_out, "X", &nbytes);
+    apr_file_flush(wsgi_signal_pipe_out);
 
-    return 0;
+    wsgi_daemon_shutdown++;
 }
 
 static int wsgi_start_process(apr_pool_t *p, WSGIDaemonProcess *daemon);
@@ -8380,19 +8587,31 @@
     apr_status_t rv;
     apr_status_t thread_rv;
 
-    /* Block all signals from being received. */
+    apr_pollfd_t poll_fd;
+    apr_int32_t poll_count = 0;
+
+    /*
+     * Create pipe by which signal handler can notify the main
+     * thread that signal has arrived indicating that process
+     * needs to shutdown.
+     */
+
+    rv = apr_file_pipe_create(&wsgi_signal_pipe_in, &wsgi_signal_pipe_out, p);
 
-    rv = apr_setup_signal_thread();
     if (rv != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, WSGI_LOG_EMERG(rv), wsgi_server,
                      "mod_wsgi (pid=%d): Couldn't initialise signal "
-                     "thread in daemon process '%s'.", getpid(),
+                     "pipe in daemon process '%s'.", getpid(),
                      daemon->group->name);
         sleep(20);
 
         return;
     }
 
+    poll_fd.desc_type = APR_POLL_FILE;
+    poll_fd.reqevents = APR_POLLIN;
+    poll_fd.desc.f = wsgi_signal_pipe_in;
+
     /* Initialise maximum request count for daemon. */
 
     if (daemon->group->maximum_requests)
@@ -8480,7 +8699,9 @@
 
     /* Block until we get a process shutdown signal. */
 
-    apr_signal_thread(wsgi_check_signal);
+    do {
+        rv = apr_poll(&poll_fd, 1, &poll_count, -1);
+    } while (APR_STATUS_IS_EINTR(rv));
 
     ap_log_error(APLOG_MARK, WSGI_LOG_INFO(0), wsgi_server,
                  "mod_wsgi (pid=%d): Shutdown requested '%s'.",
@@ -8665,6 +8886,14 @@
         ap_close_listeners();
 
         /*
+         * Cleanup the Apache scoreboard to ensure that any
+         * shared memory segments or memory mapped files not
+         * available to code in daemon processes.
+         */
+
+        ap_cleanup_scoreboard(0);
+
+        /*
          * Wipe out random value used in magic token so that not
          * possible for user code running in daemon process to
          * discover this value for other daemon process groups.
@@ -8704,10 +8933,8 @@
 
         wsgi_daemon_shutdown = 0;
 
-        if (daemon->group->threads == 1) {
-            apr_signal(SIGINT, wsgi_signal_handler);
-            apr_signal(SIGTERM, wsgi_signal_handler);
-        }
+        apr_signal(SIGINT, wsgi_signal_handler);
+        apr_signal(SIGTERM, wsgi_signal_handler);
 
         /*
          * Flag whether multiple daemon processes or denoted
@@ -8854,6 +9081,37 @@
         entry = &entries[i];
 
         /*
+         * Check for whether the daemon process user and
+         * group are the default Apache values. If they are
+         * then reset them to the current values configured for
+         * Apache. This is to work around where the User/Group
+         * directives had not been set before the WSGIDaemonProcess
+         * directive was used in configuration file. In this case,
+         * where no 'user' and 'group' options were provided,
+         * the default values would have been used, but these
+         * were later overridden thus why we need to update it.
+         */
+
+        if (entry->uid == ap_uname2id(DEFAULT_USER)) {
+            entry->uid = unixd_config.user_id;
+            entry->user = unixd_config.user_name;
+
+            ap_log_error(APLOG_MARK, WSGI_LOG_DEBUG(0), wsgi_server,
+                         "mod_wsgi (pid=%d): Reset default user for "
+                         "daemon process group '%s' to uid=%ld.",
+                         getpid(), entry->name, (long)entry->uid);
+        }
+
+        if (entry->gid == ap_gname2id(DEFAULT_GROUP)) {
+            entry->gid = unixd_config.group_id;
+
+            ap_log_error(APLOG_MARK, WSGI_LOG_DEBUG(0), wsgi_server,
+                         "mod_wsgi (pid=%d): Reset default group for "
+                         "daemon process group '%s' to gid=%ld.",
+                         getpid(), entry->name, (long)entry->gid);
+        }
+
+        /*
          * Calculate path for socket to accept requests on and
          * create the socket.
          */
@@ -9380,6 +9638,14 @@
         }
     }
 
+    /*
+     * Need to reset request status value to HTTP_OK else it
+     * screws up HTTP input filter when processing a POST
+     * request with 100-continue requirement.
+     */
+
+    r->status = HTTP_OK;
+
     /* Transfer any request content which was provided. */
 
     seen_eos = 0;
@@ -9805,7 +10071,7 @@
 
     r->filename = (char *)apr_table_get(r->subprocess_env, "SCRIPT_FILENAME");
 
-    if ((rv = apr_stat(&r->finfo, r->filename, APR_FINFO_SIZE,
+    if ((rv = apr_stat(&r->finfo, r->filename, APR_FINFO_NORM,
                        r->pool)) != APR_SUCCESS) {
         /*
          * Don't fail at this point. Allow the lack of file to
@@ -10036,6 +10302,7 @@
 
 static void wsgi_hook_child_init(apr_pool_t *p, server_rec *s)
 {
+#if defined(MOD_WSGI_WITH_DAEMONS)
     WSGIProcessGroup *entries = NULL;
     WSGIProcessGroup *entry = NULL;
 
@@ -10053,6 +10320,7 @@
             entry->listener_fd = -1;
         }
     }
+#endif
 
     /* Setup Python in Apache worker processes. */
 
diff -Nru mod-wsgi-2.3/README mod-wsgi-2.5/README
--- mod-wsgi-2.3/README	2008-03-13 06:30:23.000000000 +0100
+++ mod-wsgi-2.5/README	2009-03-07 02:00:17.000000000 +0100
@@ -2,7 +2,7 @@
 Welcome to MOD_WSGI
 ===================
 
-Copyright 2007 GRAHAM DUMPLETON
+Copyright 2007-2009 GRAHAM DUMPLETON
 
 The mod_wsgi adapter is an Apache module that provides a WSGI compliant
 interface for hosting Python based web applications within Apache. The

Attachment: signature.asc
Description: Digital signature


Reply to: