diff --git a/moo/kernel/Context.moo b/moo/kernel/Context.moo index 810437c..ff26271 100644 --- a/moo/kernel/Context.moo +++ b/moo/kernel/Context.moo @@ -321,7 +321,7 @@ class(#pointer) CompiledMethod(Object) preamble_data_2, ntmprs, nargs, - //code, <-- only if moo is built with MOO_USE_METHOD_TRAILER disable. + //code, <-- only if moo is built with MOO_USE_METHOD_TRAILER disabled. dbi_file_offset, dbi_method_offset. diff --git a/moo/kernel/Moo.moo b/moo/kernel/Moo.moo index a2fc329..d7b277a 100644 --- a/moo/kernel/Moo.moo +++ b/moo/kernel/Moo.moo @@ -2,10 +2,10 @@ #include 'Context.moo'. #include 'Except.moo'. #include 'Class.moo'. -#include 'System.moo'. #include 'Boolean.moo'. #include 'Magnitu.moo'. #include 'Collect.moo'. +#include 'System.moo'. #include 'Process.moo'. #include 'Stream.moo'. diff --git a/moo/kernel/System.moo b/moo/kernel/System.moo index d44e169..1de7d72 100644 --- a/moo/kernel/System.moo +++ b/moo/kernel/System.moo @@ -13,7 +13,7 @@ class System(Apex) var(#class) asyncsg. var(#class) gcfin_sem. var(#class) gcfin_should_exit := false. - var(#class) shr. + var(#class) shr. // signal handler registry pooldic Log { @@ -31,12 +31,8 @@ class System(Apex) method(#class) _initialize { - self.shr := Dictionary new. - } - - method(#class) _cleanup - { - self.shr := nil. + self.shr := Set new. + self.asyncsg := SemaphoreGroup new. } method(#class) addAsyncSemaphore: sem @@ -54,11 +50,21 @@ class System(Apex) ^self.asyncsg wait. } + method(#class) installSignalHandler: block + { + self.shr add: block. + } + + method(#class) uninstallSignalHandler: block + { + self.shr remove: block. + } + method(#class) startup(class_name, method_name) { | class ret gcfin_proc ossig_proc | - self.asyncsg := SemaphoreGroup new. + System gc. class := self at: class_name. // System at: class_name. if (class isError) @@ -150,7 +156,7 @@ class System(Apex) [ while (true) { - while ((tmp := self _getSig) notError) + until ((tmp := self _getSig) isError) { // TODO: Do i have to protected this in an exception handler??? //TODO: Execute Handler for tmp. @@ -160,18 +166,14 @@ class System(Apex) // user-defined signal handler is not allowed for 16rFF if (tmp == 16rFF) { goto done }. - /* - sh := self.sighandler at: tmp. - if (sh isNil) - {*/ - // the default action for sigint(2) is to terminate all processes. - if (tmp == 2) { goto done }. - /*} + ifnot (self.shr isEmpty) + { + self.shr do: [ :handler | handler value ] + } else { - // invoke a user-defined signal handler if available. - sh value: tmp. - }*/ + if (tmp == 2) { goto done }. + }. }. os_intr_sem wait. }. @@ -218,7 +220,6 @@ class System(Apex) self.gcfin_sem signal. // wake the gcfin process. self _halting. // inform VM that it should get ready for halting. - self _cleanup. ]. } @@ -237,14 +238,6 @@ class System(Apex) method(#class,#primitive) return: object to: context. // ======================================================================================= - method(#class) registerSignalHandler: block - { - self.shr add: block. - } - - method(#class) removeSignalHandler: block - { - } method(#class) sleepForSecs: secs { diff --git a/moo/kernel/X11.moo b/moo/kernel/X11.moo index 745d8e2..7be4848 100644 --- a/moo/kernel/X11.moo +++ b/moo/kernel/X11.moo @@ -37,10 +37,11 @@ class X11(Object) [X11able,selfns.X11able3] from "x11" // ===================================================================== var shell_container := nil. - var window_registrar. // all windows registered + var window_registry. // all windows registered var event_loop_sem, event_loop_proc. var llevent_blocks. + var event_loop_exit_req := false. method(#dual) abc { ^nil } @@ -119,7 +120,7 @@ TODO: TODO: compiler enhancement { | w | w := self _create_window(parent_window_handle, x, y, width, height, fgcolor, bgcolor). - if (w notError) { self.window_registrar at: w put: owner }. + if (w notError) { self.window_registry at: w put: owner }. ^w } @@ -128,7 +129,7 @@ TODO: TODO: compiler enhancement | w | //#('DESTROY ' & window_handle asString) dump. w := self _destroy_window(window_handle). - if (w notError) { self.window_registrar removeKey: window_handle } + if (w notError) { self.window_registry removeKey: window_handle } } } @@ -598,7 +599,7 @@ extend X11 super initialize. self.shell_container := self.Composite new. - self.window_registrar := System.Dictionary new: 100. + self.window_registry := System.Dictionary new: 100. /* @@ -654,6 +655,7 @@ extend X11 { if (self.event_loop_sem isNil) { + self.event_loop_sem := Semaphore new. self.event_loop_sem signalOnInput: (self _get_fd). self.event_loop_proc := [ @@ -661,19 +663,23 @@ extend X11 [ | llevtbuf llevent ongoing | + self.event_loop_exit_req := false. llevtbuf := X11.LLEvent new. ongoing := true. while (self.shell_container childrenCount > 0) { 'Waiting for X11 event...' dump. + if (self.event_loop_exit_req) { break }. self.event_loop_sem wait. - if (ongoing not) { break }. + if (self.event_loop_exit_req) { break }. + ifnot (ongoing) { break }. while ((llevent := self _get_llevent(llevtbuf)) notNil) { if (llevent isError) { //System logNl: ('Error while getting a event from server ' & self.cid asString). + self.event_loop_exit_req := true. ongoing := false. break. } @@ -715,11 +721,17 @@ extend X11 self.event_loop_sem signal. } + method requestToExit + { + self.event_loop_exit_req := true. + self.event_loop_sem signal. + } + method __dispatch_llevent: llevent { | widget mthname | - widget := self.window_registrar at: llevent window ifAbsent: [ + widget := self.window_registry at: llevent window ifAbsent: [ System logNl: 'Event on unknown widget - ' & (llevent window asString). ^nil ]. @@ -793,6 +805,15 @@ class Fx(Object) class MyObject(Object) { var disp1, disp2, shell1, shell2, shell3. + var on_sig. + + method initialize + { + self.on_sig := [:sig | + self.disp1 requestToExit. + self.disp2 requestToExit. + ]. + } method main1 { @@ -828,6 +849,8 @@ class MyObject(Object) self.shell2 realize. self.shell3 realize. + System installSignalHandler: self.on_sig. + self.disp1 enterEventLoop. // this is not a blocking call. it spawns another process. self.disp2 enterEventLoop. @@ -836,7 +859,6 @@ class MyObject(Object) comp1 := Fx new. Fx new. - while (self.disp1 isConnected or self.disp2 isConnected) { System sleepForSecs: 1 }. } diff --git a/moo/lib/gc.c b/moo/lib/gc.c index 1e8e035..0b6c682 100644 --- a/moo/lib/gc.c +++ b/moo/lib/gc.c @@ -405,7 +405,7 @@ static kernel_class_info_t kernel_classes[] = { 6, { 'S','y','s','t','e','m' }, 0, - 3, /* asyncsg, gcfin_sem, gcfin_should_exit*/ + 4, /* asyncsg, gcfin_sem, gcfin_should_exit, shr */ 0, 0, MOO_OBJ_TYPE_OOP, @@ -835,9 +835,8 @@ static moo_uint8_t* scan_heap_space (moo_t* moo, moo_uint8_t* ptr, moo_uint8_t** { moo_oow_t size; - /* TODO: is it better to use a flag bit in the header to - * determine that it is an instance of process? - * for example, if (MOO_OBJ_GET_FLAGS_PROC(oop))... */ + /* is it really better to use a flag bit in the header to + * determine that it is an instance of process? */ if (MOO_UNLIKELY(MOO_OBJ_GET_FLAGS_PROC(oop))) { /* the stack in a process object doesn't need to be