trying to implement user-defined signal handling mechanism
This commit is contained in:
		@ -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.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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'.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -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 }.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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 
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user