Safe Exit code

This forum is for general developer support questions.
Post Reply
LiveForIt
Posts: 8
Joined: Tue Jul 05, 2011 2:41 pm

Safe Exit code

Post by LiveForIt »

I’m trying to write a safe exit code, where the main program should wait for all child processes to quit, before quitting.

I have normally used death massage, to do this, but under heavy CPU load, it can some time get case where the main program some how quits before the child process, anyway.

So this method is not 100% safe, I was thinking about, giving the child process a unique names like

gfx_engine_ff22dd33dd, where ff22dd33dd be the mains programs FindTask(NULL) pointer,
And check if child exists in permit forbid lock.

for(;;)
{
child_process =0;
forbid();
if (FindTask(GFXPROCESS)) child_process++;
if (FindTask(SOUNDPROCESS)) child_process++;
if (FindTask(NETWORKPROCESS)) child_process++;
if (FindTask(NETWORKPROCESS)) child_process++;
permit();
Delay(1);
if (child_process == 0) break;
}

but somehow I think this might be over complicated, there most be way just query how many child process that are running? Without reinventing the wheel or coming up with hacks.

I like some kind of function like.

while (have_child_process()) Delay();
User avatar
thomasrapp
Posts: 310
Joined: Sat Jun 18, 2011 11:22 pm

Re: Safe Exit code

Post by thomasrapp »

FindTask is not a good thing to use for private processes.

You should rather design the child tasks so that they signal the main task in Forbid() state only at the very end of the routine. Just use Workbench as a model.

So the last few lines of each child process should be either

Code: Select all

Forbid()
ReplyMsg (message);
}
or

Code: Select all

Forbid()
ReleaseSemaphore (semaphore);
}
The former implies that the main task sends some kind of message to the child. Either a startup message which is held all the time the child lives or a quit message which causes the child to quit.

The latter is less synchron. It just ensures that all children have left before the main program can quit, without keeping track of all child tasks. It works so that the main routine sets up a signal semaphore and each child calls ObtainSemaphoreShared for this semaphore. At the end of the main program you just call ObtainSemaphore which will wait until all shared locks are removed before it can obtain the exclusive lock.
User avatar
broadblues
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 600
Joined: Sat Jun 18, 2011 2:40 am
Location: Portsmouth, UK
Contact:

Re: Safe Exit code

Post by broadblues »

I have normally used death massage, to do this, but under heavy CPU load, it can some time get case where the main program some how quits before the child process, anyway.
If the death mesage approach fails at all, let alone in high CPU, you have an error in your code!.

Start your processes with NP_CHild,TRUE,NP_NotifyOnDeathMessage,dmsg,

where dmsg is the correctly filled out struct DeathMessage structure with reply port etc..

Keep a count of the processes open increment for every process started and decrement it for every death message received at the end of the main program execuation (or whereever you need to reap your children).

The final loop should look something like the folowing taken from the CreateNewProcess AutoDoc:

Code: Select all

	          while( childcount >0 )
	          {
	             iexec->WaitPort(DMreplyport);
	             while(( dmsg = (APTR)iexec->GetMsg(DMreplyport) ))
	             {
	                idos->PutStr("Death message received for child.\n");
	                iexec->FreeVec(dmsg);
	                childcount --;
	             }
	          }
User avatar
colinw
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 207
Joined: Mon Aug 15, 2011 9:20 am
Location: Brisbane, QLD. Australia.

Re: Safe Exit code

Post by colinw »

I have written extensive example code in the autodocs for this particular situation. (as broadblues mentioned)
Please review dos.doc file -> CreateNewProc().

If you don't have a relatively recent dos.doc file that has the three examples at the bottom,
send me a PM with your email address and I can send one to you.

Please also avoid calling Forbid() or Permit(), they are not required for user code to perform
robust subprocess exit arbitration on OS4.

I would recommend the first example that uses a semaphore with the NP_EntryCode and NP_FinalCode vectors.
User avatar
colinw
AmigaOS Core Developer
AmigaOS Core Developer
Posts: 207
Joined: Mon Aug 15, 2011 9:20 am
Location: Brisbane, QLD. Australia.

Re: Safe Exit code

Post by colinw »

thomasrapp wrote: You should rather design the child tasks so that they signal the main task in Forbid() state only at the very end of the routine.
It doesn't work if any child process crashes, it will leave the parent process hung forever.
While ever the arbitration mechanism is dependant on the child process executing some particular piece of its code,
you are going to end up in a hung parent processs if something goes wrong and that code never gets called.

I created the NP_EntryCode and NP_FinalCode vectors specifically to allow things like this sort of arbitration code
to execute within the dos.library context, before and after the user code is actually executed.
These vectors also get executed when a process is "killed" by the grimreaper.
Therefore, it would be extremely wise to always use a mechanism that always gets executed by DOS, regardless.

The NP_EntryCode and NP_FinalCode vector method is the simplest and is the first example in the autodoc.
The second example uses the DeathMessage, this too always gets sent even when a child process is "killed".
The third example is a bit more complex and uses a process change notification in conjunction with searching the process
list for any remaining children.

All of them are "kill safe" and will always result in correct exit arbitration.
Post Reply