cvsuser     04/02/08 11:42:09

  Modified:    include/parrot interpreter.h
               src      events.c
               t/pmc    nci.t
  Log:
  event-handling-23
  * fix a bug WRT missing sleep wakeups:
    Event handlers like callbacks or timer subs run as plain
    code in a plain runloop, so they can be interrupted by other
    events. When that event was the wakeup for a sleep event it got lost.
    Now sleeping is an interpreter variable to avoid this event leak.
  
  Revision  Changes    Path
  1.120     +2 -1      parrot/include/parrot/interpreter.h
  
  Index: interpreter.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/interpreter.h,v
  retrieving revision 1.119
  retrieving revision 1.120
  diff -u -w -r1.119 -r1.120
  --- interpreter.h     7 Feb 2004 12:58:46 -0000       1.119
  +++ interpreter.h     8 Feb 2004 19:42:04 -0000       1.120
  @@ -1,7 +1,7 @@
   /* interpreter.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: interpreter.h,v 1.119 2004/02/07 12:58:46 leo Exp $
  + *     $Id: interpreter.h,v 1.120 2004/02/08 19:42:04 leo Exp $
    *  Overview:
    *     The interpreter api handles running the operations
    *  Data Structure and Algorithms:
  @@ -264,6 +264,7 @@
       PMC** nci_method_table;       /* Method table PMC for NCI stubs per class */
       size_t nci_method_table_size;       /* allocated size of this table */
       struct QUEUE* task_queue;           /* per interpreter queue */
  +    int sleeping;                       /* used durning sleep in events */
       struct parrot_exception_t *exceptions; /* internal exception stack */
       struct parrot_exception_t *exc_free_list; /* and free list */
       struct _Thread_data *thread_data;   /* thread specific items */
  
  
  
  1.30      +29 -13    parrot/src/events.c
  
  Index: events.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/events.c,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -w -r1.29 -r1.30
  --- events.c  7 Feb 2004 12:58:53 -0000       1.29
  +++ events.c  8 Feb 2004 19:42:07 -0000       1.30
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: events.c,v 1.29 2004/02/07 12:58:53 leo Exp $
  +$Id: events.c,v 1.30 2004/02/08 19:42:07 leo Exp $
   
   =head1 NAME
   
  @@ -909,17 +909,23 @@
   {
       QUEUE_ENTRY *entry;
       parrot_event* event;
  -    int sleeping = 1;
  +    QUEUE * tq = interpreter->task_queue;
  +    interpreter->sleeping = 1;
  +    /*
  +     * event handler likes callbacks or timers are run as normal code
  +     * so inside such an even handler function another event might get
  +     * handled, which is good (higher priority events can interrupt
  +     * other event handler OTOH we must ensure that all state changes
  +     * are done in do_event and we should probably suspend nested
  +     * event handlers sometimes
  +     *
  +     */
   
  -    while (sleeping) {
  -        entry = wait_for_entry(interpreter->task_queue);
  +    while (interpreter->sleeping) {
  +        entry = wait_for_entry(tq);
           event = (parrot_event* )entry->data;
           mem_sys_free(entry);
  -        if (event->type == EVENT_TYPE_SLEEP && event->data == next)
  -            sleeping = 0;
  -        else if (event->type == EVENT_TYPE_TERMINATE ||
  -                event->type == EVENT_TYPE_SIGNAL)
  -            sleeping = 0;
  +        edebug((stderr, "got ev %d head : %p\n", event->type, tq->head));
           next = do_event(interpreter, event, next);
       }
       return next;
  @@ -1032,6 +1038,7 @@
               next = NULL;        /* this will terminate the run loop */
               break;
           case EVENT_TYPE_SIGNAL:
  +            interpreter->sleeping = 0;
               /* generate exception */
               event_to_exception(interpreter, event);
               /* not reached - will longjmp */
  @@ -1043,12 +1050,20 @@
               break;
           case EVENT_TYPE_CALL_BACK:
               edebug((stderr, "starting user cb\n"));
  -            Parrot_runops_fromc_args(interpreter, event->u.call_back.sub,
  +            Parrot_runops_fromc_args_save(interpreter, event->u.call_back.sub,
                       "PP",
                       event->u.call_back.user_data,
                       event->u.call_back.external_data);
               break;
           case EVENT_TYPE_SLEEP:
  +            interpreter->sleeping = 0;
  +#if 0
  +            /* doesn't work do_event is called from outside too */
  +            if (!next || event->data 1= next)
  +                internal_exception(1,
  +                        "Unhandled nested sleep call: next = %p ed = %p",
  +                        next, event->data);
  +#endif
               break;
           default:
               fprintf(stderr, "Unhandled event type %d\n", event->type);
  @@ -1076,13 +1091,14 @@
   {
       QUEUE_ENTRY *entry;
       parrot_event* event;
  +    QUEUE * tq = interpreter->task_queue;
   
       if (restore)
           disable_event_checking(interpreter);
  -    if (!peek_entry(interpreter->task_queue))
  +    if (!peek_entry(tq))
           return next;
  -    while (peek_entry(interpreter->task_queue)) {
  -        entry = pop_entry(interpreter->task_queue);
  +    while (peek_entry(tq)) {
  +        entry = pop_entry(tq);
           event = (parrot_event* )entry->data;
           mem_sys_free(entry);
           next = do_event(interpreter, event, next);
  
  
  
  1.30      +1 -1      parrot/t/pmc/nci.t
  
  Index: nci.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/nci.t,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -w -r1.29 -r1.30
  --- nci.t     7 Feb 2004 16:44:33 -0000       1.29
  +++ nci.t     8 Feb 2004 19:42:09 -0000       1.30
  @@ -853,7 +853,7 @@
     set I20, 0
   loop:
     inc I20
  -  ## sleep 0.1 hangs sometimes in __select ## XXX ##
  +  #or  sleep 0.01 and loop only a few times
     find_global P11, "cb_done"
     if P11, fin
     gt I20, 100000, err
  
  
  

Reply via email to