×

Discussion Board

Results 1 to 13 of 13
  1. #1
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    E32USER-CBase 91

    Greetings,

    Does anyone know what "E32USER-CBase 91" actually means? It seems to be related to using timers, most likely trying to cancel a timer too fast? Doesn't seem to be documented too well?

    Trying to do animation with my_timer.after(0.01). However when new event comes while old animation is still going on, I try to my_timer.cancel() and then everything crashes... most likely, since I cannot debug this at all! No traceback, no log files, no printing text strings on file, no trace output. It's a quick, fast and immediate crash.

    Anyway, it would help if I understood why python crashed. Much easier to figure out a fix or workaround.

    Debugging,

    --jouni

  2. #2
    Nokia Developer Moderator
    Join Date
    Mar 2003
    Location
    Lempäälä/Finland
    Posts
    29,169

    Re: E32USER-CBase 91

    SDK docs say "This panic is raised by CActiveSchedulerWait::Start() when the CActiveSchedulerWait object has already been started. "

  3. #3
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    No matter what I do there's a crash Any ideas what I do wrong? Here's an easily crashable sample code.

    Usage:
    • press left arrow, screen turns blue
    • wait more than 1 second
    • press right arrow, screen turns green
    • press quickly left-right or right-left
    • Application closed: Python E32USER-CBase 91 crash


    Seems like I can freely choose between System Error (-50) and E32USER-CBase 91. There must be something I am totally and completely misunderstanding about timers...

    Code:
    import e32
    import appuifw
    import key_codes
    
    my_timer = e32.Ao_timer()
    app_lock = e32.Ao_lock()
    
    def draw_color(a_color):
        canvas.clear(a_color)
        # Without cancel() Python: System error (-50)
        #                  RunTimerError: Timer pending - cancel first
        # With cancel() crash
        #               E32USER-CBase 91
        my_timer.cancel()
        my_timer.after(1)
    
    appuifw.app.orientation = 'portrait'
    appuifw.app.screen = 'full'
    appuifw.app.exit_key_handler = app_lock.signal
    appuifw.app.menu = [(u"Exit", app_lock.signal)]
    appuifw.app.body = canvas = appuifw.Canvas()
    
    canvas.bind(key_codes.EKeyLeftArrow, lambda: draw_color((0, 0, 255)))
    canvas.bind(key_codes.EKeyRightArrow, lambda: draw_color((0, 255, 0)))
    
    app_lock.wait()
    Looking for work arounds,

    --jouni

  4. #4
    Super Contributor
    Join Date
    Oct 2007
    Location
    Deva, Romania
    Posts
    3,471

    Re: E32USER-CBase 91

    I seem to have found a workaround: putting my_timer.cancel() after my_timer.after(1). I'm not sure that fits with the goal of your application (if your application is more that just this script), but it seems to work.

    EDIT: Although it makes Python not crash anymore, some errors (apparently not serious ones, since they don't stop the program) are shown.

  5. #5
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    Quote Originally Posted by bogdan.galiceanu View Post
    I seem to have found a workaround: putting my_timer.cancel() after my_timer.after(1). I'm not sure that fits with the goal of your application (if your application is more that just this script), but it seems to work.

    EDIT: Although it makes Python not crash anymore, some errors (apparently not serious ones, since they don't stop the program) are shown.
    Sorry, this doesn't make sense according to manual: since I don't give any callback function to my_timer.after(1), then that call is supposed to be synchronuous and thus my_timer.cancel() would be called only after after(1) () is done in one second. Therefore cancel() after my_timer has already expired simply doesn't make sense. It's a no-op.

    Furthermore by debugging I could see that the error is as expected:

    Code:
    Traceback (most recent call last):
      File "c:\python\aa.py", line 94, in <lambda>
        canvas.bind(key_codes.EKeyRightArrow, lambda: draw_color((0, 255, 0)))
      File "c:\python\aa.py", line 40, in draw_color
        my_timer.after(1)
    RuntimeError: Timer pending - cancel first
    If I would believe in bugs, I'd say this is one. Since I don't, it's just a difficult feature we have to live with. Looks like I have to write myself some additional code to get "cancellable timer" functionality

    The app: well, it's a simple game with one animated element. One movement, either by arrow key or device tilting, would be presented in animation with x steps. If user made another move while animation was still going on, I wanted to cancel current animation and start new into possible different direction. Hmph, it does sound a lot like 16 Puzzle, but it's not. Just another simple game I've been writing several times for various platforms... Could use same animation method there, too.

    Since I cannot cancel animation at anytime by cancelling a timer, I have to think of a way to wait until timer has expired by itself. Most likely I need to add a bunch of global variables, some additional status query and clean-up routines.

    Messy

    --jouni who didn't expect Symbian C++ kind of issues with PyS60

  6. #6
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    Argh,

    Application closed:
    Python
    KERN-EXEC 3
    Recommendation: avoid timers. You cannot cancel then, while they are running. This makes exiting from application quite difficult.

    Guess I'll have to stop writing games and go back to do some sample code. Or anything but games

    --jouni collecting timer crashes

  7. #7
    Regular Contributor
    Join Date
    Sep 2005
    Location
    Finland, Helsinki
    Posts
    323

    Re: E32USER-CBase 91

    Quote Originally Posted by JOM View Post
    Recommendation: avoid timers. You cannot cancel then, while they are running.
    I have no problems with timers.

    How about creating a new timer instead of using the old one, probably not yet canceled?

    Code:
    class Something:
      # ...
      t = e32.Ao_timer()
    
      def update(self):
        self.t.cancel()
        self.t = e32.Ao_timer()
        if self.active:
          self.t.after(0.5, self.update)
        else:
          self.t.cancel()
    
      def close(self):
        self.t.cancel()
        # ...

  8. #8
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    Quote Originally Posted by aaaaapo View Post
    I have no problems with timers.

    How about creating a new timer instead of using the old one, probably not yet canceled?

    Code:
    class Something:
      # ...
      t = e32.Ao_timer()
    
      def update(self):
        self.t.cancel()
        self.t = e32.Ao_timer()
        if self.active:
          self.t.after(0.5, self.update)
        else:
          self.t.cancel()
    
      def close(self):
        self.t.cancel()
        # ...
    !!! WOW !!!

    I'm multitasking, supposed to do something else, but since I haven't slept at weekend during timer crashes, I check DiBo several times a day... Just in case, desperately hoping for a miracle - which you most likely just delivered !!!

    Looks like using a CALLBACK solves the whole problem! At least my crash sample didn't crash any more! Should have worked as-is, according to manual, but happy to adapt to async usage! Can't believe I missed that, it's not like Timers API would be too complicated Can't wait till next night coding session, hoping to stay awake!

    Amazed,

    --jouni

  9. #9
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    Nope,

    Timers are incredibly broken piece of software. They should be removed from next PyS60 update to save future developers from a very painful experience - or at least some functional sample code should be provided. Or documented, if timers work in different way in emulator vs. real devices (I crash real devices less often, mostly just emulator).

    Just to document last crashes:

    Crash 1) Manual says "call to after returns immediately and the callback gets called after interval". In my debug traces callback is called immediately, regardless of interval. What's even worse is that original function is never "return"ed and thus I get this crash (below). My callback calls itself, with time interval "100", which should be enough to change canvas color and return. But there are never any returns, it's endless recursion until:

    Python:
    System error (-50)
    Which is clarified in debug output as:

    RuntimeError: maximum recursion depth exceeded
    Crash 2) When I limit the number of recursion into 3, things get more interesting. First the default error note:

    Python:
    System error (-50)
    Which is clarified in debug output as:

    ===== RETURN c:\python\aa.py draw_color@43: if g_count < 3:
    c:\python\aa.py draw_color@45: my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    c:\python\aa.py draw_color@45: my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    c:\python\aa.py draw_color@45: my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    c:\python\aa.py <lambda>@100: canvas.bind(key_codes.EKeyLeftArrow, lambda: draw_color((0, 0, 255)))
    Traceback (most recent call last):
    File "c:\python\aa.py", line 100, in <lambda>
    canvas.bind(key_codes.EKeyLeftArrow, lambda: draw_color((0, 0, 255)))
    File "c:\python\aa.py", line 45, in draw_color
    my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    File "c:\python\aa.py", line 45, in draw_color
    my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    File "c:\python\aa.py", line 45, in draw_color
    my_timer.after(100, draw_color((random.choice(range(0,255)), random.choice(range(0,255)), random.choice(range(0,255)))))
    TypeError: callable expected for 2nd argument
    When looking at e32module.cpp file, you find:

    Code:
    extern "C" PyObject *
    ao_timer_after(Ao_timer_object *self, PyObject* args)
    {
      TReal d;
      PyObject* c=NULL;
    
      if (!PyArg_ParseTuple(args, "d|O", &d, &c))
        return NULL;
    
      if (c && !PyCallable_Check(c)) {
        PyErr_SetString(PyExc_TypeError, "callable expected for 2nd argument");
        return NULL;
      }
      ...
      #ifndef EKA2
      self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000).GetTInt()), c);
      #else
      self->ob_data->After(TTimeIntervalMicroSeconds32(TInt64(d*1000*1000)), c);
      #endif /*EKA2*/
    I'm wondering why the very first return from callback function is checking whether c (callback function) is callable or not. I'M RETURNING from callback, c is used only to setup the callback in the first place!

    Looks like call stack handling is buggy somehow, that timers would not work in emulator at all == recall that there were problems in emulator with multitasking. However I crashed this same code in N82, too. Multitasking should be possible in real device, so the reason has to be something else.

    Flubbergusted,

    --jouni who simply cannot make timers work

  10. #10
    Registered User
    Join Date
    May 2008
    Posts
    6

    Re: E32USER-CBase 91

    Heh, I used timer in one program for status bar type thing, and through experimentation guessed that the time parameter is seconds. It works for me, but when the app quits it takes the entire python shell with it too...

    Maybe because i'm trying to cancel the timer in the exitkey handler, and it infact crashes? I don't have anything installed that would help me distinguish between an app quitting and an app crashing.

  11. #11
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Talking Re: E32USER-CBase 91

    Finally!

    The ... very nice ... timer callback DOES NOT take any parameters! How could I have known, nothing indicated anything like that. Maybe it's basic python stuff, but I had no idea. Well, I sure do know it now

    Also like shadowjk told, the time interval SEEMS to be seconds.

    Next step will be difficult. I SHOULD write sample code about how to use timers and why certain things have to be done in certain ways, but I have two games waiting for update. What a wonderful problem

    Happy,

    --jouni after 4 different documented timer crashes and at least two more which he just ignored out of desperation

  12. #12
    Regular Contributor
    Join Date
    Sep 2005
    Location
    Finland, Helsinki
    Posts
    323

    Re: E32USER-CBase 91

    Quote Originally Posted by JOM View Post
    Finally!

    The ... very nice ... timer callback DOES NOT take any parameters! How could I have known, nothing indicated anything like that. Maybe it's basic python stuff - -
    Yes it is. You can use anonymous lambda-function if you need to use parametes:

    Code:
    >>> import e32, time
    >>> start = time.clock()
    >>> def foo(x):
    ...   print "%s after %.3f secs" % (x, time.clock() - start)
    ... 
    >>> t = e32.Ao_timer()
    >>> t.after(1.5, lambda:foo("Jeejee"))
    >>> Jeejee after 1.594 secs

  13. #13
    Super Contributor
    Join Date
    Mar 2003
    Location
    Espoo, Finland
    Posts
    976

    Re: E32USER-CBase 91

    Quote Originally Posted by aaaaapo View Post
    Yes it is. You can use anonymous lambda-function if you need to use parametes:

    Code:
    >>> import e32, time
    >>> start = time.clock()
    >>> def foo(x):
    ...   print "%s after %.3f secs" % (x, time.clock() - start)
    ... 
    >>> t = e32.Ao_timer()
    >>> t.after(1.5, lambda:foo("Jeejee"))
    >>> Jeejee after 1.594 secs
    Oooh...

    I did have lambda in original crash sample (beginning of this thread), but that nasty "E32USER-CBase 91" crash made me remove it - and then I forgot Well, it's beginning to look better, there can't be too many mistakes left, can there?

    I've summarized all crashes as sample code on my webpages. Easier to check, what all those error codes meant and what was the fix.

    Thanx,

    --jouni

Similar Threads

  1. Error E32USER - CBase 21
    By PankajNeve in forum Symbian
    Replies: 10
    Last Post: 2007-11-27, 10:18
  2. Error E32USER - CBase 71
    By NigelT in forum Symbian
    Replies: 2
    Last Post: 2007-02-13, 22:28
  3. E32User Cbase 21
    By Tina_Tibrewal in forum Symbian User Interface
    Replies: 3
    Last Post: 2006-10-05, 11:13
  4. program closed ERROR: E32USER Cbase 63
    By jha_pankaj18 in forum Symbian User Interface
    Replies: 1
    Last Post: 2004-05-12, 20:17

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
×