<div dir="ltr"><div>Hi Andrew,</div><div><br></div><div>Does a poll_interval of 0.5 mean that the server is checking for new http requests ever 0.5 seconds (seems long)?</div><div><br></div><div>It is pretty unpredictable how many tasklets are waiting to run while the webserver is handling requests. Most likely there will be many, but any that depend on IO (like sending an email) i would like to hand over to  worker threads (eventually, not in the demo i am polishing right now), but a substantial number of processes/tasklets have no IO at all. They are started through channels, either fed by server requests or e.g. timers. </div>
<div><br></div><div>I also have timers running e.g. for processes/tasklets that are started periodically. For now they are checking datetime.now() (or some such) every time their tasklet is run, but in the future i need something better, at least let all timers be handled by one tasklet in total.</div>
<div><br></div><div>With the tasklets.schedule() in the server_forever loop (keeping poll_interval at 0.5) i occasionally (1 in 10 server starts) get the following exception. Any ideas what might be the cause?  </div><div>
<br></div><div>----------------------------------------</div><div>Exception happened during processing of request from ('127.0.0.1', 60867)</div><div>Traceback (most recent call last):</div><div>  File "C:\python27\lib\SocketServer.py", line 295, in _handle_request_noblock</div>

<div>    self.process_request(request, client_address)</div><div>  File "C:\python27\lib\SocketServer.py", line 321, in process_request</div><div>    self.finish_request(request, client_address)</div><div>  File "C:\python27\lib\SocketServer.py", line 334, in finish_request</div>

<div>    self.RequestHandlerClass(request, client_address, self)</div><div>  File "C:\python27\lib\SocketServer.py", line 649, in __init__</div><div>    self.handle()</div><div>  File "C:\python27\lib\wsgiref\simple_server.py", line 121, in handle</div>

<div>    self.rfile, self.wfile, self.get_stderr(), self.get_environ()</div><div>  File "C:\python27\lib\wsgiref\simple_server.py", line 74, in get_environ</div><div>    env = self.server.base_environ.copy()</div>

<div>AttributeError: StacklessWSGIServer instance has no attribute 'server'</div><div>----------------------------------------</div><div><br></div><div>Cheers, Lars</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Thu, Dec 12, 2013 at 5:27 PM, Andrew Francis <span dir="ltr"><<a href="mailto:andrewfr_ice@yahoo.com" target="_blank">andrewfr_ice@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div><div style="font-size:12pt;font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif"><div><span>Hi Lars:</span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">
<span><br></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span>What I am suggesting is:</span></div>
<div class="im"><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span><br></span></div><div>
>def serve_forever(self, poll_interval=0.5):</div><div>>      
  self._BaseServer__is_shut_down.clear()</div><div>>        try:</div><div>>            while not self._BaseServer__shutdown_request:</div><div style="background-color:transparent"><span></span></div><div>>                r, w, e = SocketServer._eintr_retry(select.select, [self], [], [], >poll_interval)</div>
<div><br></div></div><div>write a function that does:</div><div><br></div><div>if stackless.getruncount() > 1:</div><div>    # we want to give tasklets that are ready to run a chance in case</div><div>    # of  low I/O <span style="font-size:12pt"> activity</span></div>
<div>    poll_interval = .5</div><div>else:</div><div>    poll_interval = some_other_large_value</div><div class="im"><div>r, w, e = SocketServer._eintr_retry(select.select, [self], [], [], poll_interval)<br></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">
<span><br></span></div></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span>My thinking is you want to cut down on needless returns and expensive system calls. </span></div>
<div style="display:block"> <br> I am also assuming you don't have some timer function that depends on the polling...</div><div style="display:block"><br></div><div style="display:block">Cheers,</div><div style="display:block">
Andrew</div><div><div class="h5"><div style="display:block"><br></div><div style="display:block"><br> <div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">
 <div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt"> <div dir="ltr"> <font face="Arial"> On Thursday, December 12, 2013 5:15 AM, lars van Gemerden <<a href="mailto:lars@rational-it.com" target="_blank">lars@rational-it.com</a>> wrote:<br>
 </font> </div>  <div><div><div><div dir="ltr">what i have now (in relation to the default simpleserver use of bottle.py) is:<div><br clear="none"></div><div>#-------------------------------------------------------------------------------------</div>
<div>from bottle import Bottle, ServerAdapter<br clear="none">
</div><div><div>from wsgiref.simple_server import WSGIServer, make_server, WSGIRequestHandler</div><div>import select, SocketServer</div><div><br clear="none"></div><div>class StacklessWSGIServer(WSGIServer): </div><div>
    def serve_forever(self, poll_interval=0.5):</div>
<div>        self._BaseServer__is_shut_down.clear()</div><div>        try:</div><div>            while not self._BaseServer__shutdown_request:</div><div>                r, w, e = SocketServer._eintr_retry(select.select, [self], [], [], poll_interval)</div>

<div>                if self in r:</div><div>                    self._handle_request_noblock()</div><div>                tasklets.schedule()</div><div>        finally:</div><div>            self._BaseServer__shutdown_request = False</div>

<div>            self._BaseServer__is_shut_down.set()</div><div>        </div><div>class MyWSGIRefServer(ServerAdapter):</div><div>    server = None</div><div><br clear="none"></div><div>    def run(self, handler):</div>
<div>        self.server = make_server(self.host, self.port, handler, </div>
<div>                                  server_class=StacklessWSGIServer, **self.options)</div><div>        self.server.serve_forever()</div><div><br clear="none"></div><div>    def stop(self):</div><div>        self.server.shutdown()</div>

<div><br clear="none"></div><div><div>app = Bottle()<br clear="none"></div></div><div><br clear="none"></div><div>           </div><div>def start_server(world_model):</div><div>    config = world_model.config</div><div>    manager = WebManager(world = world_model, secret = "jhbv235gfuhbvq2345hy3bo0")</div>

<div>    setattr(sys.modules[__name__], "manager", manager)</div><div>    server = MyWSGIRefServer(host=config.WS_HOST, port=config.WS_PORT)</div><div>    tasklets.tasklet(app.run)(server = server, debug = config.WS_DEBUG)</div>

<div>    return server</div></div><div><br clear="none"></div><div><div>#-------------------------------------------------------------------------------------</div><div><br clear="none"></div></div><div>I did this mainly by some reverse engineering, not by  really understanding the server code.</div>

<div><br clear="none"></div><div>Cheers, Lars</div></div><div><br clear="none"><br clear="none"><div><div>On Thu, Dec 12, 2013 at 2:07 AM, Andrew Francis <span dir="ltr"><<a rel="nofollow" shape="rect" href="mailto:andrewfr_ice@yahoo.com" target="_blank">andrewfr_ice@yahoo.com</a>></span> wrote:<br clear="none">

<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div style="font-size:12pt;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><div>

<div><div style="font-size:12pt;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><div><span>Hi Folks:</span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">

<span><br clear="none"></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span>This is what I am suggesting. The reactor tasklet before calling the
 underlying select/poll system call should look at the scheduler queue. If there are runnable tasklets, then call select/poll with a timeout. Otherwise block indefinitely. The idea is if your application is consists of mostly I/O bound tasklets, they will be blocked on channels and will eventually be scheduled and run when there is I/O for them.</span></div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span><br clear="none"></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">

<span>I'll write a
 simple example to illustrate.....</span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">

<span><br clear="none"></span></div><div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span>Cheers,</span></div>

<div style="font-style:normal;font-size:16px;background-color:transparent;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><span>Andrew</span></div><div><div>
<div><div style="display:block"> <br clear="none"> <br clear="none"> <div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt"> <div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">

 <div dir="ltr"> <font face="Arial"> On Wednesday, December 11, 2013 7:00 AM, lars van Gemerden <<a rel="nofollow" shape="rect" href="mailto:lars@rational-it.com" target="_blank">lars@rational-it.com</a>> wrote:<br clear="none">
 </font> </div>
  <div><div><div><div dir="ltr">Hi Andrew,<div><br clear="none"></div><div>It wasn't
 blocked on IO, the server got stuck in it's mainloop (or similar name). I don't know much about webservers, WSGIservers etc, but what i also tried was putting a schedule() in this mainloop (which i think polls the socket). Is this what you suggest? It seems to work well, apart from the occasional weird AttributeError, which i'll have to look into. However others discouraged this approach, but i never quite understood why. </div>


<div><br clear="none"></div><div>Cheers, Lars</div></div><div><br clear="none"><br clear="none"><div>On Fri, Dec 6, 2013 at 7:40 PM, Andrew Francis <span dir="ltr"><<a rel="nofollow" shape="rect" href="mailto:andrewfr_ice@yahoo.com" target="_blank">andrewfr_ice@yahoo.com</a>></span> wrote:<br clear="none">


<blockquote style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div style="font-size:12pt;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif">

<div>
<div><div style="font-size:12pt;font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif"><div><span>Hi Lars:</span></div><div style="display:block"><div><div><div dir="ltr" style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">


<br clear="none"></div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">Message: 1<br clear="none">Date: Thu, 5 Dec 2013 22:07:20
 +0100<br clear="none">From: lars van Gemerden <<a rel="nofollow" shape="rect" href="mailto:lars@rational-it.com" target="_blank">lars@rational-it.com</a>><br clear="none">To: The Stackless Python Mailing List <<a rel="nofollow" shape="rect" href="mailto:stackless@stackless.com" target="_blank">stackless@stackless.com</a>><br clear="none">


Subject: Re: [Stackless] monkeypatching<br clear="none">Message-ID:<br clear="none">    <CAP8kt8yLp1P46DeZfdBwkeTvWmbWFXbAra+<a rel="nofollow" shape="rect" href="mailto:MSxViXhuWXj0Fsw@mail.gmail.com" target="_blank">MSxViXhuWXj0Fsw@mail.gmail.com</a>><br clear="none">


Content-Type: text/plain; charset="windows-1252"<br clear="none"><br clear="none">>(oh, i created a tasklet for the bottle microframework run() method, which<br clear="none">>includes the mainn server loop()) ; I only called schedule() on
 each web<br clear="none">>server request to be able to do anything outside the server mainloop.<br clear="none">>However that had the
 effect that process steps where not executed as >long as the end user sent no requests (some processes do not have any >web component).<br clear="none"></div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">


<br clear="none"></div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">I haven't had a chance to carefully look at your code. However from this description, it sounds like a thread/tasklet is blocked on I/O.  This will have the effect of blocking all tasklets in that thread. What you need to do is occasionally call a timeout from the underlying system call (for example, select()) and do a schedule() so other tasklets can
 run.</div><div> <br clear="none"></div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">Cheers,</div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">


Andrew</div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt"><br clear="none"></div><div style="font-family:HelveticaNeue,'Helvetica Neue',Helvetica,Arial,'Lucida Grande',sans-serif;font-size:12pt">


P.S - Yahoo's new and improved mail interface is killing me!</div>  </div> </div>  </div> </div></div></div></div></div></div><br clear="none">_______________________________________________<br clear="none">
Stackless mailing list<br clear="none">
<a rel="nofollow" shape="rect" href="mailto:Stackless@stackless.com" target="_blank">Stackless@stackless.com</a><br clear="none">
<a rel="nofollow" shape="rect" href="http://www.stackless.com/mailman/listinfo/stackless" target="_blank">http://www.stackless.com/mailman/listinfo/stackless</a><br clear="none"></blockquote></div><br clear="none"><br clear="all">

<div><br clear="none"></div>-- <br clear="none">====================================<br clear="none">
Lars van Gemerden<br clear="none"><a rel="nofollow" shape="rect" href="mailto:lars@rational-it.com" target="_blank">lars@rational-it.com</a><br clear="none"><a rel="nofollow" shape="rect">+31 6 26 88 55 39</a><br clear="none">

====================================
</div></div></div><br clear="none"><br clear="none"></div>  </div> </div>  </div></div> </div></div></div></div></div></div></div></blockquote></div></div><br clear="none"><br clear="all"><div><br clear="none"></div>-- <br clear="none">
====================================<br clear="none">
Lars van Gemerden<br clear="none"><a rel="nofollow" shape="rect" href="mailto:lars@rational-it.com" target="_blank">lars@rational-it.com</a><br clear="none"><a href="tel:%2B31%206%2026%2088%2055%2039" value="+31626885539" target="_blank">+31 6 26 88 55 39</a><br clear="none">
====================================
</div></div></div><br><br></div>  </div> </div>  </div> </div></div></div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br>====================================<br>Lars van Gemerden<br><a href="mailto:lars@rational-it.com">lars@rational-it.com</a><br>
+31 6 26 88 55 39<br>====================================
</div>