added ProcessScheduler>>processById:

attempting to correct signal handling behavior
This commit is contained in:
hyunghwan.chung 2019-08-18 17:46:40 +00:00
parent 071ebb7788
commit 42df4239a6
6 changed files with 156 additions and 32 deletions

View File

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

View File

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

View File

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

View File

@ -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,6 +657,8 @@ 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.
@ -677,15 +683,17 @@ extend X11
}.
}.
}.
] ensure: [
'CLOSING X11 EVENT LOOP' dump.
self.event_loop_sem unsignal.
// TODO: LOOK HERE FOR RACE CONDITION
// TODO: LOOK HERE FOR RACE CONDITION with exitEventLoop.
self.event_loop_sem := nil.
self.event_loop_proc := nil.
self dispose.
[ 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
}
}

View File

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

View File

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