From: Joshua B. <JRB...@lb...> - 2007-03-27 18:03:28
|
I think I made too much of the statement for "each hit", but the documentation clearly states what you have said. Here is another simple way to do this. Obviously there would be some performance consequence, but one could make a "copy" of the module and dump it into "AsHandler". And use a closure to cleanup before returning. It's ~15 lines of code, and could be modified in order to adapt to a different interface. This is untested code. -josh import sys, ZSI, types from mod_python import apache, util from ZSI.dispatch import AsHandler import TEST def closure(func): def callfunc(*args, **kw): r = func(get_request(), *args, **kw) del_request() return r return callfunc CTEST = types.ModuleType() for k,v in filter(lambda k,v: callable(v), TEST.__dict__.items()): setattr(CTEST, k, closure(v)) def get_request(): return CTEST.REQUEST def set_request(request): #global CTEST CTEST.REQUEST = request def del_request(): #global CTEST del CTEST.REQUEST def handler(req): if req.method == 'GET': req.content_type = "text/html" req.send_http_header() req.write("""<html><head><title>2.1.3 A mod_python example</ title></head><body>ZSI: %s </body></html>""" %ZSI.__file__) return apache.OK elif req.method == 'POST': # find handlers set_request(req) AsHandler(req, modules=[CTEST,], rpc=True) return apache.OK return apache.DECLINED On Mar 26, 2007, at 2:54 PM, Graham Dumpleton wrote: > On Mar 27, 4:12 am, Joshua Boverhof <JRBover...@lbl.gov> wrote: >> But mod_python uses a subinterpreter to handle each request, so how >> is any of this relevant? > > Wrong. A separate sub interpreter is NOT used to handle each request. > This is a common misconception that continues to be propagated by a > few people who haven't looked very well into how mod_python actually > works. > > It is true that mod_python uses sub interpreters, but once one is > created for handling some subset of the URL namespace, by default one > per virtual host, the sub interpreter persists for the life of the > process. Any requests that then arrive for that subset of the URL > namespace are then handled within the context of the sub interpreter. > If Apache uses a multithreaded MPM such as on Windows or worker MPM on > UNIX, then that sub interpreter could be hosting concurrently > executing requests handlers in different threads. > >> Also if I'm setting the global for each request I don't see how I >> could ever access the request object and cause Apache to crash. > > The mod_python request object is just a wrapper for an internal Apache > data structure. The memory for that internal Apache data structure is > free up at the end of the request regardless of whether the Python > wrapper still exists or not. Thus, if you retain a reference to the > mod_python request object beyond the life time of the request, as a > global variable or otherwise, and then subsequently access it in some > way, you will be accessing freed memory, or worse memory that has > since been allocated for some other purpose. If modifications were > made to that free/reused memory in some way through the interface of > the mod_python request object you could potentially corrupt memory > used by something else and thus crash Apache. This is not theoretical > as we have seen users on the mod_python list who have managed to do > exactly this and crash Apache. > >> -josh >> >> On Mar 23, 2007, at 2:38 PM, Graham Dumpleton wrote: >> >>> Using a global like that is dangerous. In a multithreaded Apache MPM >>> such as on Windows or worker on UNIX, you will have multiple >>> concurrent request handlers running and they will be competing >>> for the >>> use of the global. Also, leaving a reference around to the >>> mod_python >>> request object after the request has finished like that will cause >>> Apache to crash if the request object is subsequently accessed. >> >>> So, in general this is bad practice, but if you must do it, use >>> thread >>> local storage and ensure that reference is deleted when request >>> finishes by using a try/finally construct. >> >>> Graham >> >>> On Mar 24, 6:16 am, Joshua Boverhof <JRBover...@lbl.gov> wrote: >>>> I'd to understand your problem a bit more, but I think I can >>>> offer a >>>> simple solution. >> >>>> You could set a global in the mod_python hander, and access it in >>>> your callbacks. >> >>>> -josh >> >>>> import sys, ZSI >>>> from mod_python import apache, util >>>> from ZSI.dispatch import AsHandler >>>> import TEST >> >>>> def handler(req): >>>> if req.method == 'GET': >>>> req.content_type = "text/html" >>>> req.send_http_header() >>>> req.write("""<html><head><title>2.1.3 A mod_python example</ >>>> title></head><body>ZSI: %s </body></html>""" %ZSI.__file__) >>>> return apache.OK >> >>>> elif req.method == 'POST': >>>> TEST.Request = req >>>> AsHandler(req, modules=[TEST,], rpc=True) >>>> return apache.OK >> >>>> else: >>>> return apache.DECLINED >> >>>> -josh >> >>>> On Mar 23, 2007, at 2:27 AM, Luca Montecchiani wrote: >> >>>>> Hi, >> >>>>> in a mod_python environment we need to receive the "req" as the >>>>> first >>>>> parameter of the called soap function. >> >>>>> The mod_python req is stored in kw['request'] by >>>>> _ModPythonSendXML() >>>>> so we wrote a simple attached patch that work for us. >> >>>>> We know that this is a workaround so if there is a better solution >>>>> we will happy to know! >> >>>>> thanks in advance, >>>>> luca >>>>> --- dispatch.py Fri Jan 26 19:01:11 2007 >>>>> +++ TS_dispatch.py Fri Mar 23 10:10:21 2007 >>>>> @@ -3,6 +3,7 @@ >>>>> '''Simple CGI dispatching. >>>>> ''' >> >>>>> + >>>>> import types, os, sys >>>>> from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer >>>>> from ZSI import * >>>>> @@ -62,7 +63,11 @@ >> >>>>> _client_binding = ClientBinding(ps) >>>>> if docstyle: >>>>> - result = handler(ps.body_root) >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of the >>>>> called function >>>>> + result = handler(kw['request'],ps.body_root) >>>>> + else : >>>>> + result = handler(ps.body_root) >>>>> tc = TC.XML(aslist=1, pname=what+'Response') >>>>> elif not rpc: >>>>> try: >>>>> @@ -77,7 +82,11 @@ >>>>> return >> >>>>> try: >>>>> - result = handler(arg) >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of >>>>> the called function >>>>> + result = handler(kw['request'],*arg) >>>>> + else : >>>>> + result = handler(*arg) >>>>> except Exception,ex: >>>>> SendFault(FaultFromZSIException(ex), **kw) >> >>>>> @@ -100,7 +109,11 @@ >>>>> SendFault(FaultFromZSIException(ex), **kw) >>>>> return >> >>>>> - result = handler(**kwargs) >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of the >>>>> called function >>>>> + result = handler(kw['request'],**kwargs) >>>>> + else : >>>>> + result = handler(**kwargs) >>>>> aslist = False >>>>> # make sure data is wrapped, try to make this a >>>>> Struct >>>>> if type(result) in _seqtypes: >>>>> @@ -120,7 +133,11 @@ >>>>> data = _child_elements(ps.body_root) >>>>> tc = TC.Any() >>>>> if isarray and len(data) == 0: >>>>> - result = handler() >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of >>>>> the called function >>>>> + result = handler(kw['request']) >>>>> + else : >>>>> + result = handler() >>>>> elif isarray: >>>>> try: arg = [ tc.parse(e, ps) for e in data ] >>>>> except EvaluateException, e: >>>>> @@ -128,14 +145,21 @@ >>>>> SendFault(RuntimeError("THIS IS AN ARRAY: % >>>>> s" % >>>>> isarray)) >>>>> return >> >>>>> - result = handler(*arg) >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of >>>>> the called function >>>>> + result = handler(kw['request'],*arg) >>>>> + else : >>>>> + result = handler(*arg) >>>>> else: >>>>> try: kwarg = dict([ (str(e.localName),tc.parse(e, >>>>> ps)) for e in data ]) >>>>> except EvaluateException, e: >>>>> SendFault(FaultFromZSIException(e), **kw) >>>>> return >>>>> - >>>>> - result = handler(**kwarg) >>>>> + if kw.has_key('request') : >>>>> + # Use modpython req as the first parameter of >>>>> the called function >>>>> + result = handler(kw['request'],**kwargs) >>>>> + else : >>>>> + result = handler(**kwargs) >> >>>>> # reponse typecode >>>>> #tc = getattr(result, 'typecode', TC.Any(pname=what >>>>> +'Response')) >>>>> ------------------------------------------------------------------ >>>>> -- >>>>> -- >>>>> --- >>>>> Take Surveys. Earn Cash. Influence the Future of IT >>>>> Join SourceForge.net's Techsay panel and you'll get the chance to >>>>> share your >>>>> opinions on IT & business topics through brief surveys-and earn >>>>> cash >>>>> http://www.techsay.com/default.php? >>>>> page=join.php&p=sourceforge&CID=DEVDEV____________________________ >>>>> __ >>>>> __ >>>>> _______________ >>>>> Pywebsvcs-talk mailing list >>>>> Pywebsvcs-t...@lists.sourceforge.net >>>>> https://lists.sourceforge.net/lists/listinfo/pywebsvcs-talk >>>>> Also archived athttp://groups.google.com/group/pywebsvcs >> >>>> smime.p7s >>>> 3KDownload >> >>>> ------------------------------------------------------------------- >>>> -- >>>> ---- >>>> Take Surveys. Earn Cash. Influence the Future of IT >>>> Join SourceForge.net's Techsay panel and you'll get the chance to >>>> share your >>>> opinions on IT & business topics through brief surveys-and earn >>>> cashhttp://www.techsay.com/default.php? >>>> page=join.php&p=sourceforge&CID=DE... >> >>>> _______________________________________________ >>>> Pywebsvcs-talk mailing list >>>> Pywebsvcs-t...@lists.sourceforge.nethttps://lists.sourceforge.net/ >>>> lists/listinfo/pywebsvcs-talk >>>> Also archived athttp://groups.google.com/group/pywebsvcs >> >>> -------------------------------------------------------------------- >>> -- >>> --- >>> Take Surveys. Earn Cash. Influence the Future of IT >>> Join SourceForge.net's Techsay panel and you'll get the chance to >>> share your >>> opinions on IT & business topics through brief surveys-and earn cash >>> http://www.techsay.com/default.php? >>> page=join.php&p=sourceforge&CID=DEVDEV >>> _______________________________________________ >>> Pywebsvcs-talk mailing list >>> Pywebsvcs-t...@lists.sourceforge.net >>> https://lists.sourceforge.net/lists/listinfo/pywebsvcs-talk >>> Also archived athttp://groups.google.com/group/pywebsvcs >> >> >> >> smime.p7s >> 3KDownload >> >> --------------------------------------------------------------------- >> ---- >> Take Surveys. Earn Cash. Influence the Future of IT >> Join SourceForge.net's Techsay panel and you'll get the chance to >> share your >> opinions on IT & business topics through brief surveys-and earn >> cashhttp://www.techsay.com/default.php? >> page=join.php&p=sourceforge&CID=DE... >> >> _______________________________________________ >> Pywebsvcs-talk mailing list >> Pywebsvcs-t...@lists.sourceforge.nethttps://lists.sourceforge.net/ >> lists/listinfo/pywebsvcs-talk >> Also archived athttp://groups.google.com/group/pywebsvcs > > > ---------------------------------------------------------------------- > --- > Take Surveys. Earn Cash. Influence the Future of IT > Join SourceForge.net's Techsay panel and you'll get the chance to > share your > opinions on IT & business topics through brief surveys-and earn cash > http://www.techsay.com/default.php? > page=join.php&p=sourceforge&CID=DEVDEV > _______________________________________________ > Pywebsvcs-talk mailing list > Pyw...@li... > https://lists.sourceforge.net/lists/listinfo/pywebsvcs-talk > Also archived at http://groups.google.com/group/pywebsvcs |