trying to implement user-defined signal handling mechanism

This commit is contained in:
hyunghwan.chung 2019-09-15 15:41:24 +00:00
parent d2f5446ee5
commit a640650b67
5 changed files with 55 additions and 41 deletions

View File

@ -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.

View File

@ -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'.

View File

@ -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
{

View File

@ -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 }.
}

View File

@ -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