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