Concurrent processes (waiting for children)

Discussion in 'Perl Misc' started by Jacob Heider, May 7, 2004.

  1. Jacob Heider

    Jacob Heider Guest

    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
    Jacob Heider, May 7, 2004
    #1
    1. Advertising

  2. Jacob Heider

    Sam Holden Guest

    On Fri, 07 May 2004 07:08:51 GMT, Jacob Heider <> wrote:
    > 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...]

    --
    Sam Holden
    Sam Holden, May 7, 2004
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Pep
    Replies:
    6
    Views:
    810
  2. Wernt Me

    multiple concurrent processes

    Wernt Me, Jan 3, 2006, in forum: Java
    Replies:
    7
    Views:
    485
    Andrew McDonagh
    Jan 4, 2006
  3. loudking
    Replies:
    1
    Views:
    245
    Eric Sosman
    May 17, 2007
  4. monk
    Replies:
    5
    Views:
    107
  5. Replies:
    2
    Views:
    133
Loading...

Share This Page