Concurrent processes (waiting for children)

J

Jacob Heider

I've been following clpm for some months now, so hopefully I'll be able
to do this in a way that doesn't offend anyone.

I'm trying to write a console-based replacement for Grip, a
CD-ripper/-encoder under linux. In theory, I should be able to encode
the wav files while ripping subsequent once, since the actual CD-ripping
is IO-bound. The obvious way (to me, at least) is to fork a child to do
the encoding, and tell subsequent children not to start working until
prior children finish. (I think) I know why this doesn't work, i.e. the
first child isn't a child of the second child, etc., so waitpid won't
work. I know there got to be a better way, and probably at least a
half-dozen ways which could work. Please help.

The code (excerpt) which doesn't work is (some lines split to get under
72-characters):


#!/usr/bin/perl

use warnings;
use strict;

my $lastpid;

for (my $i = 1; $i <= 5; $i++) {

system("cdda2wav -D /dev/cdrom -I cooked_ioctl -P 0 -t $i"
"-O wav -H -g $i.wav") == 0
or die "cdda2wav failed: $?\n";

my $childpid = fork;
die "fork failed: $?\n" unless defined($childpid);

if ($childpid == 0) {

if ($lastpid) {
waitpid($lastpid, 0);
}

system("lame -V 3 $i.wav $i.mp3") == 0
or die "lame failed: $?\n";
system("oggenc -q 3 -o $i.ogg $i.wav") == 0
or die "oggenc failed: $?\n";
system("flac -6 -o $i.flac $i.wav") == 0
or die "flac failed: $?\n";

system("rm $i.wav");

exit;

}

$lastpid = $childpid;
}

__END__

The system calls could be anything, of course, but these are the
applications I'm calling. I have looked a Parallel::ForkManager, but
since this project is to get me into perl from a primarily C background,
I'm trying to be thorough in exploring my options.

Someday I hope to wrap this baby in a quality curses GUI (since I'm sick
to death of non-text apps), but if I can get the guts to run, I'll be
most of the way towards having something useful.

Thanks for the help,

Jacob
 
S

Sam Holden

I've been following clpm for some months now, so hopefully I'll be able
to do this in a way that doesn't offend anyone.

I'm trying to write a console-based replacement for Grip, a
CD-ripper/-encoder under linux. In theory, I should be able to encode
the wav files while ripping subsequent once, since the actual CD-ripping
is IO-bound. The obvious way (to me, at least) is to fork a child to do
the encoding, and tell subsequent children not to start working until
prior children finish. (I think) I know why this doesn't work, i.e. the
first child isn't a child of the second child, etc., so waitpid won't
work. I know there got to be a better way, and probably at least a
half-dozen ways which could work. Please help.

I'd approach it by forking a process that just keeps encoding
files until told to stop it would look something like:

#note: completely untested... not even executed once...

sub encode_files {
while (my $file = <READER>) {
chomp $file;
system("lame -V 3 $file.wav $file.mp3") == 0
or die "lame failed: $?\n";
system("oggenc -q 3 -o $file.ogg $file.wav") == 0
or die "oggenc failed: $?\n";
system("flac -6 -o $file.flac $file.wav") == 0
or die "flac failed: $?\n";
}
}

#create a pipe
pipe(READER,WRITER) or die "Unable to pipe: $!";
$| = 1, select $_ for select WRITER;

#fork a child and set it to work
my $childpid = fork();
die "fork failed: $?\n" unless defined($childpid);
if ($childpid == 0) {
encode_files();
exit(0);
}

for my $i (1 ... 5) {
system("cdda2wav -D /dev/cdrom -I cooked_ioctl -P 0 -t $i" .
"-O wav -H -g $i.wav") == 0
or die "cdda2wav failed: $?\n";
print WRITER "$i\n";
}
close WRITER;
wait();


Though I'd use the list form of system to stop the shell from
seeing the commands, and I'd pass an IO::Handle or a GLOB reference
to encode_files.

There might be blocking issues with the pipe, in which case you could
use a temporary file, and treat a blank line as a terminate signal
instead of eof.

I guess you could just open( WRITER, "|xargs [appropriate arguments")
where two of the appropriate arguments will be -l and -i instead of
the fork and child loop.

[snip code, most of which has been copied into the code above...]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top