Apart from the bug you found (and crafted by me), your example illustrates some 
of the shortcomings of monkeypatching.

The framework you are working with is clearly using socket.select() to do 
timeouts when listening to connections.  This is fairly common in Python 
(socketserver.py does this) but IMHO bad practice.

First, "accept" itself can timeout and python oughty to simply better support 
timeout in that api.

Second, there is no "asynchronous" select.  We monkeypatch select by farming it 
off to a worker thread.

In a stackless application this introduces latency.



To accept a connection, your application has to wake up from select(), then 
enter an accept() state and then wake up from that.



Select() is not a nice API and the reason we do IO in stackless (using multiple 
tasklets) is generally in order to avoid using select().



K

________________________________
From: [email protected] [[email protected]] on 
behalf of lars van Gemerden [[email protected]]
Sent: Sunday, December 01, 2013 1:58 PM
To: The Stackless Python Mailing List
Subject: Re: [Stackless] monkeypatching

OK, thanks for the input,

i am trying to get this to work, but i might have found a bug (which i find 
hard to debug):

i have reimplemented the code above as:
--------------------------------------------------------------
import asyncore, traceback, sys, logging

import stacklesslib.main
import stacklesslib.app

# the unittests use time.time() for various time tests.
# Therefore, we must make sure that main uses this
from time import time as elapsed_time
stacklesslib.main.elapsed_time = elapsed_time

class MonkeyTasklets(object):

    _stop = False

    stacklesslib.app.install_stackless()

    @classmethod
    def run(cls, world, webserver = None, maxcount = None): #param killer is 
ignored
        world.flowmodel.start()
        if webserver:
            cls.server = webserver.start_server(world_model = world) #starts a 
tasklet for running the webserver
        counter = 0
        while not cls._stop or counter > maxcount:
            counter += 1
            tick_time = elapsed_time()
            try:
                stacklesslib.main.mainloop.loop()
            except Exception as e:
                import asyncore
                if isinstance(e, ReferenceError):
                    print("run:EXCEPTION", str(e), asyncore.socket_map)
                else:
                    print("run:EXCEPTION", asyncore.socket_map)
                    traceback.print_exc()
                sys.exc_clear()
        world.flowmodel.stop()

    @classmethod
    def schedule(cls):
        stackless.schedule()

    @classmethod
    def tasklet(cls, func):
        return stackless.tasklet(func)

    @classmethod
    def stop(cls):
        if hasattr(cls, "server"):
            cls.server.stop()
        cls._stop = True


tasklets = MonkeyTasklets

--------------------------------------------------------------
 and i get the exception:

File "d:\Documents\Code\python\floware\server\bottle.py", line 641, in run
  run(self, **kwargs)
File "d:\Documents\Code\python\floware\server\bottle.py", line 2720, in run
  server.run(app)
File "d:\Documents\Code\python\floware\server\webserver.py", line 329, in run
  self.server.serve_forever()
File "C:\Python27\lib\SocketServer.py", line 236, in serve_forever
  poll_interval)
File "C:\Python27\lib\SocketServer.py", line 155, in _eintr_retry
  return func(*args)
File "d:\Documents\Code\python\floware\stacklesslib\replacements\select.py", 
line 27, in select
  return stacklesslib.threadpool.call_on_thread(real_select.select, args, 
kwargs)
File "d:\Documents\Code\python\floware\stacklesslib\threadpool.py", line 123, 
in call_on_thread
  return tasklet_call(wrapped, dispatcher, timeout=timeout, 
onOrphaned=onOrphaned)
File "d:\Documents\Code\python\floware\stacklesslib\util.py", line 209, in 
tasklet_call
  return channel_wait(chan, timeout)
File "d:\Documents\Code\python\floware\stacklesslib\util.py", line 53, in 
channel_wait
  return chan.receive()
File "d:\Documents\Code\python\floware\stacklesslib\util.py", line 192, in 
helper
  result = function(*args, **kwargs)

TypeError: wrapped() argument after * must be a sequence, not function
--------------------------------------------------------------
is this something i am doing wrong or indeed a buggy in stacklesslib and if so, 
how can it be fixed?

Cheers, Lars


On Sun, Dec 1, 2013 at 4:05 AM, Richard Tew 
<[email protected]<mailto:[email protected]>> wrote:
latest stacklesslib, i mean.

On 12/1/13, Richard Tew 
<[email protected]<mailto:[email protected]>> wrote:
> Hi Lars,
>
> stacklessio is internal ccp stuff.
>
> main.py in stacklesslib is pretty much all you need to understand,
> beyond calling patch_all().  It is a scheduler, and makes your Open
> scheduler redundant.
>
> I suggest you get the latest stacklessio from:
>
> https://bitbucket.org/krisvale/stacklesslib
>
> And then you check out test / teststdlibunittests.py, which is a short
> example of monkey patching and running the stacklesslib scheduler.
>
> Cheers,
> Richard.
>
> On 12/1/13, lars van Gemerden 
> <[email protected]<mailto:[email protected]>> wrote:
>> sorry,
>>
>> patch_all seemed to simple, question was a bit rethoric ;-) tried it 2
>> mins
>> after pressing send just in case and indeed no cigar.
>>
>> I am trying to get this demo running and all kinds of last minute #### is
>> popping up.
>>
>> I tried reading the source but it doesn't click; i am not familiar with
>> using sockets etc. at all.
>>
>> e.g.
>>
>> - do i need 'stacklessio'?
>> - can i (essentially) just put a stackless.schedule() (or
>> OpenTasklets.schedule() in the code below) in the serve_forever loop?
>> - will this work at all with an adapted scheduler like this:
>>
>> class OpenTasklets(object):
>>
>>     _stop = False
>>
>>     @classmethod
>>     def run(cls, maxcount = None):
>>         cls.schedule_channel = stackless.channel()
>>         cls.schedule_channel.preference = 1
>>         counter = 0
>>         OpenTasklets._stop = False
>>         while stackless.getruncount() != 1:
>>             stackless.run()
>>             cls.reschedule(cls._stop or (maxcount and counter >
>> maxcount))
>>             counter += 1
>>
>>     @classmethod
>>     def schedule(cls):
>>         if cls.schedule_channel.receive():
>>             raise TaskletExit
>>
>>     @classmethod
>>     def reschedule(cls, stop = False):
>>         while cls.schedule_channel.balance < 0:
>>             cls.schedule_channel.send(stop)
>>
>> Any help is appreciated ..
>>
>> Lars
>>
>>
>>
>>
>> On Sat, Nov 30, 2013 at 8:53 PM, Richard Tew
>> <[email protected]<mailto:[email protected]>>wrote:
>>
>>> Lars :-)
>>>
>>> Yes, there is no documentation for stacklesslib yet.  To use it, you
>>> really need to be willing to read the source code.
>>>
>>> You should already know whether calling patch_all would be enough.  It
>>> would have been something you could have tried immediately, rather
>>> than asking the list and waiting.
>>>
>>> Cheers,
>>> Richard.
>>>
>>> On 11/30/13, lars van Gemerden 
>>> <[email protected]<mailto:[email protected]>> wrote:
>>> > Hi all,
>>> >
>>> > I though i could avoid it to run my demo but it seems i need to let
>>> > the
>>> > webserver (simple server?, single thread, 'bottle' micro framework)
>>> > yield
>>> > to the scheduler i am using. I have downloaded stacklesslib 1.0.3, but
>>> > can't find any documentation to help with monkeypatching.
>>> >
>>> > - Do i just run patch_all at the start of the program?
>>> >
>>> > Any help is very welcome ..
>>> >
>>> > Cheers, Lars
>>> >
>>> > --
>>> > ====================================
>>> > Lars van Gemerden
>>> > [email protected]<mailto:[email protected]>
>>> > +31 6 26 88 55 39<tel:%2B31%206%2026%2088%2055%2039>
>>> > ====================================
>>> >
>>>
>>> _______________________________________________
>>> Stackless mailing list
>>> [email protected]<mailto:[email protected]>
>>> http://www.stackless.com/mailman/listinfo/stackless
>>>
>>
>>
>>
>> --
>> ====================================
>> Lars van Gemerden
>> [email protected]<mailto:[email protected]>
>> +31 6 26 88 55 39<tel:%2B31%206%2026%2088%2055%2039>
>> ====================================
>>
>

_______________________________________________
Stackless mailing list
[email protected]<mailto:[email protected]>
http://www.stackless.com/mailman/listinfo/stackless



--
====================================
Lars van Gemerden
[email protected]<mailto:[email protected]>
+31 6 26 88 55 39[X]
====================================
_______________________________________________
Stackless mailing list
[email protected]
http://www.stackless.com/mailman/listinfo/stackless

Reply via email to