<br><br><div class="gmail_quote">On Mon, Feb 20, 2012 at 8:09 PM, Eric Larson <span dir="ltr">&lt;<a href="mailto:eric@ionrock.org">eric@ionrock.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
CherryPy provides a bus that allows you to add events to the web server process. It is specified pretty clearly and CherryPy recently made it available as a standalone package, Magicbus (<a href="https://bitbucket.org/cherrypy/magicbus/overview" target="_blank">https://bitbucket.org/cherrypy/magicbus/overview</a>). Specifically it allows you to send events on different signals the main server process might get. You can also use it for a general bus within the app server, but at its most basic level, the goal was to make the stop/start/restart events easy to hook into.<br>

<br>
I&#39;ve found it to be really helpful for managing processes and wrote a simple supervisor-ish app called Dad using it (<a href="http://bitbucket.org/elarson/dad" target="_blank">http://bitbucket.org/elarson/dad</a>).<br>
</blockquote><div><br>Thanks for the pointer -- that looks pretty neat<br><br>I would be more interested though, in defining an extension to the WSGI standard<br><br>A rough example of what I am talking about:<br><br>If I take the wsgiref doc, here&#39;s an example of a minimal wsgi application (myapp.py):<br>
<br>
<div style class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">wsgiref.simple_server</span> <span class="kn">import</span> <span class="n">make_server</span><br><br><span class="k">def</span> <span class="nf">hello_world_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
    <span class="n">status</span> <span class="o">=</span> <span class="s">&#39;200 OK&#39;</span> <span class="c"># HTTP Status</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;Content-type&#39;</span><span class="p">,</span> <span class="s">&#39;text/plain&#39;</span><span class="p">)]</span> 
    <span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">[</span><span class="s">&quot;Hello World&quot;</span><span class="p">]</span>

<span class="n">def main():<br></span><span class="o"></span> <span class="n">return make_server</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">,</span> <span class="n">hello_world_app</span><span class="p">)</span><br>
<span class="k"></span> <br><br></pre></div>
</div>That module can be run by any web server out there that understands WSGI. For instance, with gunicorn I can do:<br><br>$ gunicorn myapp:main<br><br>What I am talking about is a second entry point for the shutdown - example:<br>

<br>

<div style class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">wsgiref.simple_server</span> <span class="kn">import</span> <span class="n">make_server</span><br><br><span class="k">def</span> <span class="nf">hello_world_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
    <span class="n">status</span> <span class="o">=</span> <span class="s">&#39;200 OK&#39;</span> <span class="c"># HTTP Status</span>
    <span class="n">headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">&#39;Content-type&#39;</span><span class="p">,</span> <span class="s">&#39;text/plain&#39;</span><span class="p">)]</span> 
    <span class="n">start_response</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">[</span><span class="s">&quot;Hello World&quot;</span><span class="p">]</span>

<span class="n">def main():<br></span><span class="o"></span> <span class="n">  return make_server</span><span class="p">(</span><span class="s">&#39;&#39;</span><span class="p">,</span> <span class="mi">8000</span><span class="p">,</span> <span class="n">hello_world_app</span><span class="p">)</span><br>
<br>def shutdown():   # or maybe something else as an argument I don&#39;t know<br>   do_some_cleanup()<br><span class="k"></span> <br><br></pre></div>
</div>
And point the shutdown callable to a web server:<br><br>$ gunicorn myapp:main myapp:shutdown<br><br>If this is defined in the WSGI standard it means any wsgi web server could call shutdown() , not only gunicorn<br><br>Cheers<br>
Tarek<br><br><br></div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
HTH<br>
<br>
Eric<br>
<br>
--<br>
Eric Larson<br>
<div><div class="h5"><br>
<br>
On Monday, February 20, 2012 at 10:03 AM, Tarek Ziadé wrote:<br>
<br>
&gt; Hello<br>
&gt;<br>
&gt; I need to be able to call a function when the web application shuts down (SIGTERM/SIGINT) -- the use case is to stop a background thread.<br>
&gt;<br>
&gt; I am currently using signals because it seems to be the most clean way to do this. atexit is much trickier since you don&#39;t know when it&#39;s going to get called and you might try to call objects that were garbage collected unless you hack something to keep references alive.<br>

&gt;<br>
&gt; But signals are also tricky beasts since you may compete with other code that are listening to them. For instance mod_wsgi don&#39;t like apps that have signal handlers.<br>
&gt;<br>
&gt; Anyways, the bottom line is that the cleanest way to do this -- as per Chris McDonough idea, would be to introduce in the WSGI protocol a &quot;shutdown&quot; function the servers would be obligated to call before exiting.<br>

&gt;<br>
&gt; I am not sure yet about its arguments, maybe a signum + frame or simply an exit code...<br>
&gt;<br>
&gt; But how do you like the idea ? That would solve for me the problem of having to deal differently here depending on if I am called with mod_wsgi or gunicorn or xxx<br>
&gt;<br>
&gt;<br>
&gt; Cheers<br>
&gt; Tarek<br>
&gt;<br>
&gt; --<br>
&gt; Tarek Ziadé | <a href="http://ziade.org" target="_blank">http://ziade.org</a><br>
</div></div>&gt; _______________________________________________<br>
&gt; Web-SIG mailing list<br>
&gt; <a href="mailto:Web-SIG@python.org">Web-SIG@python.org</a> (mailto:<a href="mailto:Web-SIG@python.org">Web-SIG@python.org</a>)<br>
&gt; Web SIG: <a href="http://www.python.org/sigs/web-sig" target="_blank">http://www.python.org/sigs/web-sig</a><br>
&gt; Unsubscribe: <a href="http://mail.python.org/mailman/options/web-sig/eric%40ionrock.org" target="_blank">http://mail.python.org/mailman/options/web-sig/eric%40ionrock.org</a><br>
<br>
<br>
<br>
</blockquote></div><br><br clear="all"><br>-- <br>Tarek Ziadé | <a href="http://ziade.org">http://ziade.org</a><br>