diff --git a/moo/kernel/Except.moo b/moo/kernel/Except.moo index f9d1e5f..4b96332 100644 --- a/moo/kernel/Except.moo +++ b/moo/kernel/Except.moo @@ -183,7 +183,11 @@ extend Context ctx basicAt: pending_pos put: false. eb value. }*/ - if (ctx basicAt: pending_pos test: true put: false) { eb value }. + if (ctx basicAt: pending_pos test: true put: false) + { + // TODO: what is the best way to handle an exception raised in an ensure block? + [ eb value ] on: Exception do: [:ex | System logNl: "WARNING: unhandled exception in ensure block - " & ex messageText ]. + }. }. stop := (ctx == context). ctx := ctx sender. diff --git a/moo/kernel/Process.moo b/moo/kernel/Process.moo index f2077e3..e5d9882 100644 --- a/moo/kernel/Process.moo +++ b/moo/kernel/Process.moo @@ -43,8 +43,15 @@ class(#pointer,#final,#limited) Process(Object) // the process must not be scheduled. // ---------------------------------------------------------------------------------------------------------- + // if the current active process(thisProcess) is not the process to terminate(self), + // suspend the target process so that no scheduling wakes the process until this + // termination is completed. //if (Processor activeProcess ~~ self) { self suspend }. if (thisProcess ~~ self) { self suspend }. + + // TODO: what if there is another process that may resume this suspended process. + // should i mark it unresumable? + self.currentContext unwindTo: self.initialContext return: nil. ^self _terminate } @@ -422,4 +429,7 @@ class(#final,#limited) ProcessScheduler(Object) method activeProcess { ^self.active } method resume: aProcess { ^aProcess resume } + + method(#primitive,#lenient) _processById: id. + method(#primitive) processById: id. } diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index 96a943c..af6db13 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -146,12 +146,33 @@ class System(Apex) nil. ] ensure: [ + | pid proc | os_intr_sem unsignal. System logNl: '>>>>Requesting to terminate the caller process ' & (caller id) asString. // the caller must request to terminate all its child processes.. - // TODO: to avoid this, this process must enumerate all proceses and terminate them. + // TODO: to avoid this, this process must enumerate all proceses and terminate them except this and gcfin process + +/* TODO: redo the following process termination loop. + need to write a proper process enumeration methods. + 0 -> startup <--- this should also be stored in the 'caller' variable. + 1 -> __gc_finalizer + 2 -> __os_signal_handler + 3 -> application main + the following loops starts from pid 3 up to 100. this is POC only. i need to write a proper enumeration methods and use them. + */ + pid := 3. + while (pid < 100) + { + //proc := Processor processById: pid. + proc := Processor _processById: pid. + if (proc notError) { System logNl: ("Requesting to terminate process of id - " & pid asString). proc terminate }. + pid := pid + 1. + }. +/* TODO: end redo */ + caller terminate. + //(Processor _processById: 1) resume. <---- i shouldn't do ths. but, this system causes VM assertion failure. fix it.... System logNl: '>>>>End of OS signal handler process ' & (thisProcess id) asString. ]. diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 76ee5bd..7435fe3 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -467,7 +467,7 @@ class X11.Composite(X11.Widget) | link | if (widget parent ~~ self) { - selfns.Exception sinal: "Cannot remove an unknown widget" + selfns.Exception signal: "Cannot remove an unknown widget" }. link := self.children findIdenticalLink: widget. @@ -573,6 +573,11 @@ extend X11 self.display_base dump. } + method isConnected + { + ^self.display_base notNil + } + method dispose { if (self.shell_container notNil) @@ -625,7 +630,6 @@ extend X11 self.LLEventType.CLIENT_MESSAGE -> #__handle_client_message:on:, self.LLEventType.SHELL_CLOSE -> #__handle_shell_close:on: }. - } method addShell: shell @@ -653,39 +657,43 @@ extend X11 self.event_loop_sem := Semaphore new. self.event_loop_sem signalOnInput: (self _get_fd). self.event_loop_proc := [ - | llevtbuf llevent ongoing | - llevtbuf := X11.LLEvent new. - ongoing := true. - while (self.shell_container childrenCount > 0) - { -'Waiting for X11 event...' dump. - self.event_loop_sem wait. - if (ongoing not) { break }. + [ + | llevtbuf llevent ongoing | - while ((llevent := self _get_llevent(llevtbuf)) notNil) + llevtbuf := X11.LLEvent new. + ongoing := true. + while (self.shell_container childrenCount > 0) { - if (llevent isError) +'Waiting for X11 event...' dump. + self.event_loop_sem wait. + if (ongoing not) { break }. + + while ((llevent := self _get_llevent(llevtbuf)) notNil) { - //System logNl: ('Error while getting a event from server ' & self.cid asString). - ongoing := false. - break. - } - else - { - self __dispatch_llevent: llevent. + if (llevent isError) + { + //System logNl: ('Error while getting a event from server ' & self.cid asString). + ongoing := false. + break. + } + else + { + self __dispatch_llevent: llevent. + }. }. }. - }. + ] ensure: [ 'CLOSING X11 EVENT LOOP' dump. - self.event_loop_sem unsignal. - // TODO: LOOK HERE FOR RACE CONDITION - self.event_loop_sem := nil. - self.event_loop_proc := nil. - - self dispose. + self.event_loop_sem unsignal. + // TODO: LOOK HERE FOR RACE CONDITION with exitEventLoop. + self.event_loop_sem := nil. + self.event_loop_proc := nil. + + [ self dispose ] on: Exception do: [:ex | ("WARNING: dispose failure...." & ex messageText) dump ]. + ] ] fork. } } @@ -826,10 +834,22 @@ class MyObject(Object) Fx new. comp1 := Fx new. Fx new. + + + while (self.disp1 isConnected or self.disp2 isConnected) { System sleepForSecs: 1 }. } +/* + method exitEventLoops + { + if (self.disp2 notNil) { self.disp2 exitEventLoop }. + if (self.disp1 notNil) { self.disp1 exitEventLoop }. + } +*/ + method(#class) main { + // this method returns immediately while having forked two processes with X11 event loops. ^self new main1 } } diff --git a/moo/lib/exec.c b/moo/lib/exec.c index 66723c8..9ee4d0d 100644 --- a/moo/lib/exec.c +++ b/moo/lib/exec.c @@ -615,6 +615,32 @@ static void terminate_process (moo_t* moo, moo_oop_process_t proc) MOO_OOP_TO_SMOOI(moo->processor->suspended.count), moo->sem_io_wait_count ); + if (MOO_OOP_TO_SMOOI(moo->processor->runnable.count) > 0) + { + moo_oop_process_t p; + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Runnable: "); + p = moo->processor->runnable.first; + while (p) + { + MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, " %O", p->id); + if (p == moo->processor->runnable.last) break; + p = p->ps.next; + } + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "\n"); + } + if (MOO_OOP_TO_SMOOI(moo->processor->suspended.count) > 0) + { + moo_oop_process_t p; + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "Suspended: "); + p = moo->processor->suspended.first; + while (p) + { + MOO_LOG1 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, " %O", p->id); + if (p == moo->processor->suspended.last) break; + p = p->ps.next; + } + MOO_LOG0 (moo, MOO_LOG_IC | MOO_LOG_DEBUG, "\n"); + } } else { @@ -2613,6 +2639,47 @@ static moo_pfrc_t pf_process_suspend (moo_t* moo, moo_mod_t* mod, moo_ooi_t narg return MOO_PF_SUCCESS; } +static moo_pfrc_t pf_process_scheduler_process_by_id (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) +{ + moo_oop_t rcv, id; + moo_oop_process_t proc; + + rcv = MOO_STACK_GETRCV(moo, nargs); + id = MOO_STACK_GETARG(moo, nargs, 0); + + MOO_PF_CHECK_RCV (moo, rcv == (moo_oop_t)moo->processor); + + if (MOO_OOP_IS_SMOOI(id)) + { + proc = moo->processor->runnable.first; + while (proc) + { + if (proc->id == id) + { + MOO_STACK_SETRET (moo, nargs, (moo_oop_t)proc); + return MOO_PF_SUCCESS; + } + if (proc == moo->processor->runnable.last) break; + proc = proc->ps.next; + } + + proc = moo->processor->suspended.first; + while (proc) + { + if (proc->id == id) + { + MOO_STACK_SETRET (moo, nargs, (moo_oop_t)proc); + return MOO_PF_SUCCESS; + } + if (proc == moo->processor->suspended.last) break; + proc = proc->ps.next; + } + } + + MOO_STACK_SETRETTOERROR (moo, nargs, MOO_ENOENT); + return MOO_PF_FAILURE; +} + /* ------------------------------------------------------------------ */ static moo_pfrc_t pf_semaphore_signal (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) { @@ -4114,6 +4181,8 @@ static pf_t pftab[] = { "MethodContext_findExceptionHandler:", { pf_context_find_exception_handler, 1, 1 } }, { "MethodContext_goto:", { pf_context_goto, 1, 1 } }, + { "ProcessScheduler_processById:", { pf_process_scheduler_process_by_id, 1, 1 } }, + { "Process_resume", { pf_process_resume, 0, 0 } }, { "Process_sp", { pf_process_sp, 0, 0 } }, { "Process_suspend", { pf_process_suspend, 0, 0 } }, diff --git a/moo/mod/x11.c b/moo/mod/x11.c index d730771..b8da2a6 100644 --- a/moo/mod/x11.c +++ b/moo/mod/x11.c @@ -215,7 +215,7 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) // TODO: CHECK if the receiver is an X11 object x11 = (oop_x11_t)MOO_STACK_GETRCV(moo, nargs); //MOO_ASSERT (moo, MOO_CLASSOF(moo,x11) == modctx->x11_class); - tr = moo_getobjtrailer (moo, (moo_oop_t)x11, MOO_NULL); + tr = moo_getobjtrailer(moo, (moo_oop_t)x11, MOO_NULL); disp = MOO_OOP_TO_SMPTR(x11->display); event = tr->event; @@ -254,12 +254,12 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) rect.y = event->xexpose.y; rect.width = event->xexpose.width; rect.height = event->xexpose.height; - if (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event)) + if (XCheckWindowEvent(disp, event->xexpose.window, ExposureMask, event)) { Region reg; /* merge all expose events in the event queue */ - reg = XCreateRegion (); + reg = XCreateRegion(); XUnionRectWithRegion (&rect, reg, reg); do @@ -270,7 +270,7 @@ static moo_pfrc_t pf_get_llevent (moo_t* moo, moo_mod_t* mod, moo_ooi_t nargs) rect.height = event->xexpose.height; XUnionRectWithRegion (&rect, reg, reg); } - while (XCheckWindowEvent (disp, event->xexpose.window, ExposureMask, event)); + while (XCheckWindowEvent(disp, event->xexpose.window, ExposureMask, event)); XClipBox (reg, &rect); XDestroyRegion (reg);