[comp.unix.wizards] Task sync

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (07/26/88)

  I have a problem which requires running a number of similar programs,
then a final program. It's not a make, but the solution might be applied
there, too.

  I want to start up to N tasks, and when I try to start the N+1th task
I want to hang until at least one is done. I want to do this in a
portable way which will run of reasonable BSD and USG systems.

  I have a hack which more of less works under SysV using semiphores and
stuff, but it's not portable, and a real kludge. If someone can give me
a clue on a better way I'd be grateful.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

kjk@pbhyf.PacBell.COM (Ken Keirnan) (07/27/88)

In article <11658@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes:
>
>  I have a problem which requires running a number of similar programs,
>then a final program. It's not a make, but the solution might be applied
>there, too.
>
>  I want to start up to N tasks, and when I try to start the N+1th task
>I want to hang until at least one is done. I want to do this in a
>portable way which will run of reasonable BSD and USG systems.
>
>  I have a hack which more of less works under SysV using semiphores and
>stuff, but it's not portable, and a real kludge. If someone can give me
>a clue on a better way I'd be grateful.


A relatively easy way to accomplish this similar to the way "init" works.
Keep a table of the process IDs for each child process as it is created,
then perform a "wait()".  When wait returns, check the return value for fail
(no children to wait for) and then with each value in the table.  If the
return value is "fail", or a match is found in the table, drop through and
execute the final child process.  If you need to wait on all children
prior to executing the final process, keeping track of the children is not
necessary.  In this case simply loop until wait() returns error status.

Ken Keirnan
-- 

Ken Keirnan - Pacific Bell - {att,bellcore,sun,ames,pyramid}!pacbell!pbhyf!kjk
  San Ramon, California	                    kjk@pbhyf.PacBell.COM

les@chinet.chi.il.us (Leslie Mikesell) (07/28/88)

In article <11658@steinmetz.ge.com> davidsen@crdos1.UUCP (bill davidsen) writes:
>
>  I want to start up to N tasks, and when I try to start the N+1th task
>I want to hang until at least one is done. I want to do this in a
>portable way which will run of reasonable BSD and USG systems.
>
You didn't say if the tasks all start from the same parent or if the
child processes can start new tasks also.  If one parent starts all
the processes, it should be able to just count them.  Set up a 
signal handler for SIGCLD which does a wait() and decrements the
process count, then re-enables the handler.  If you reach the maximum
tasks, just pause().  This should work at least in sysV, and unlike
other signals, you should never miss a SIGCLD.  If the child processes
are allowed to fork() also, it becomes more complicated and you would
need some form of IPC, perhaps a pipe inherited from the original
parent.  The child could write its PID down the pipe and wait for
a signal before each fork().

 Les Mikesell

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (07/29/88)

In article <11658@steinmetz.ge.com> I write:
| 
|   I have a problem which requires running a number of similar programs,
| then a final program. It's not a make, but the solution might be applied
| there, too.

  Well about 30 people have written to say that all I do is keep a PID
table, so I guess I didn't clarify the question very well. What I need
to do is something like the 'batch' command, in that the commands to be
run will not be started by the same processes, at least on its own.

  I need to be able to handle a number of commands, possibly from a
number of other programs, in a portable way.

  On SysV I have a kludge which reads a named pipe and when it gets a
command it either starts a process to execute it or waits for an
existing process to complete. I never worked on getting the status back
to the submitter, because I don't seem to find named pipes on all (or
even most) BSD systems.

  What I have now is more or less a daemon to run jobs, although I would
be willing to implement almost anything which will work. I certainly
don't mind having some code which is used for BSD and some for SysV, but
I don't want to use non-portable features and have every few lines be
more stuff in an ifdef.

Here's one way to use it:
	for file in *.mu
	do	runsome -3 ioproc $file
	#       ^^^^^^^  A ^^^^^^^^^^^^^^^^
	#   what I need  |    the command
	#         max to run
	done
	runwait
	^^^^^^^
	# wait for all to stop


It could also go in a make file:
	# compile three at a time
	.c.o: runsome -3 $(CC) $< -c

	prog:  $(OBJFILES)
		runwait
		cc $(LFLAGS) $(OBJFILES) -o prog


what I have now is more or less:
	pipename=`runsome 3`		# run just three
	for file in *.c
	do	echo "indent ${file}" > ${pipename}
	done
	runwait ${pipename}

  Thanks again to all who responded, I mailed thanks to all but some
bounced, and hopefully this time I have explained better.

-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs | seismo}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me