reimplement AsyncFileGetter
authorChristian Garbs <mitch@cgarbs.de>
Tue, 6 Oct 2015 11:36:38 +0000 (13:36 +0200)
committerChristian Garbs <mitch@cgarbs.de>
Tue, 6 Oct 2015 19:20:15 +0000 (21:20 +0200)
fork() under Perl, don't run external shell scripts

Under irssi, additional code is needed to prevent zombies
(API->{wait_for_child}).  For weechat and xchat something like this
might be needed too!

libvideosite.pm
videosite-irssi.pl
videosite/AsyncFileGetter.pm

index bf02068..f9959bf 100644 (file)
@@ -78,6 +78,7 @@ my $remote_api = {
     module_path => sub { return dirname(realpath($0)) },
     quote => sub { return $_ },
     reload => sub {},
     module_path => sub { return dirname(realpath($0)) },
     quote => sub { return $_ },
     reload => sub {},
+    wait_for_child => sub {},
 };
 
 #
 };
 
 #
@@ -276,6 +277,7 @@ sub _ploader {
                 config_get => \&_config_get,
                 config_set => \&_config_set,
                 config_has => \&_config_has,
                 config_get => \&_config_get,
                 config_set => \&_config_set,
                 config_has => \&_config_has,
+               wait_for_child => $remote_api->{wait_for_child},
             });
         } else {
             _io('%s has wrong type (got %s, expected %s)', $p, $g->{'TYPE'}, $type);
             });
         } else {
             _io('%s has wrong type (got %s, expected %s)', $p, $g->{'TYPE'}, $type);
index 043cc93..aa838c0 100644 (file)
@@ -266,6 +266,8 @@ sub videosite_reset {
         module_path => sub { return File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts') },
         quote => sub { s/%/%%/g; return $_ },
         reload => \&videosite_reset,
         module_path => sub { return File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts') },
         quote => sub { s/%/%%/g; return $_ },
         reload => \&videosite_reset,
+       # irssi needs this to prevent fork()ed child processes becoming zombies:
+       wait_for_child => sub { Irssi::pidwait_add($_[0]) },
     })) {
         Irssi::print(sprintf("videosite API register failed: %s", $libvideosite::error));
         return 0;
     })) {
         Irssi::print(sprintf("videosite API register failed: %s", $libvideosite::error));
         return 0;
index c47f9dd..1489f88 100644 (file)
@@ -1,5 +1,5 @@
 # (c) 2007 by Ralf Ertzinger <ralf@camperquake.de>
 # (c) 2007 by Ralf Ertzinger <ralf@camperquake.de>
-#     2008-2009,2011-2012 by Christian Garbs <mitch@cgarbs.de>
+#     2015 by Christian Garbs <mitch@cgarbs.de>
 #
 # licensed under GNU GPL v2
 #
 #
 # licensed under GNU GPL v2
 #
@@ -13,10 +13,6 @@ use videosite::FileGetter;
 @ISA = qw(videosite::FileGetter);
 
 use strict;
 @ISA = qw(videosite::FileGetter);
 
 use strict;
-use LWP::Simple qw(!get);
-use File::Basename;
-use File::Temp qw(tempfile);
-use MIME::Base64;
 
 sub new {
     my $class = shift;
 
 sub new {
     my $class = shift;
@@ -28,55 +24,35 @@ sub new {
     return bless($self, $class);
 }
 
     return bless($self, $class);
 }
 
-sub get {
+sub _download {
     my $self = shift;
     my $self = shift;
+    my $dlurl = shift;
+    my $dlfile = shift;
     my $video = shift;
     my $video = shift;
-    my $dlfile;
-    my $dirname;
-    my $cookie = "";
-    my $useragent = "-H \"User-Agent: Mozilla/5.0\"";
+    my $child_pid;
 
 
-    $dlfile = sprintf($self->_getval('FILEPATTERN'),
-        $self->_encode($video->{'SOURCE'}),
-        $self->_encode($video->{'ID'}),
-        $self->_encode($video->{'TITLE'}),
-        $self->_encode($video->{'DLURL'}),
-        $self->_encode($video)->{'URL'});
-
-    $dlfile =~ s/([\\"])/\\$1/g;
-
-    $dirname = dirname($dlfile);
-    if ($self->_diskfree($dirname) < $self->_getval('MINFREE')) {
-        $self->error("Not enough free space to download");
-        return 0;
-    }
-
-    $self->debug('Going to download %s to %s', $video->{'DLURL'}, $dlfile);
-
-    my (undef, $tmpfile) = tempfile('videosite.tmp.XXXXXXXXXXXX', DIR => $dirname);
-
-    my %saved_env;
+    # fork to background
+    $child_pid = fork();
     
     
-    if (exists($video->{'CONNECTOR'})) {
-        my $schemas = $video->{'CONNECTOR'}->{'schemas'};
-        foreach my $schemakey(keys(%{$schemas})) {
-            $self->debug("Setting %s_proxy to %s", $schemakey, $schemas->{$schemakey});
-            my $envkey = $schemakey.'_proxy';
-            $saved_env{ $envkey } = $ENV{ $envkey };
-            $ENV{ $envkey } = $schemas->{$schemakey};
-        }
+    if ($child_pid) {               # parent
+       $self->debug('parent spawned process %d for download', $child_pid);
+       if (exists $self->{_API}->{wait_for_child}) {
+           $self->debug('calling wait_for_child on %d', $child_pid);
+           $self->{_API}->{wait_for_child}->($child_pid);
+       }
+       Irssi::pidwait_add($child_pid);
     }
     }
-    
-    $cookie = "-H \"Cookie: $video->{'COOKIE'}\"" if (defined $video->{'COOKIE'});
-    my $cmdline = "( GET $useragent $cookie \"$video->{'DLURL'}\" > \"$tmpfile\" && mv \"$tmpfile\" \"$dlfile\" && chmod =rw \"$dlfile\" || rm -f \"$tmpfile\" ) &";
-    $self->debug(encode_base64($cmdline));
-    system($cmdline);
-
-    # restore environment
-    foreach my $envkey (keys %saved_env) {
-       $self->debug("Restoring environment: %s=%s", $envkey, $saved_env{ $envkey} );
-        $ENV{ $envkey } = $saved_env{ $envkey };
+    elsif (defined $child_pid) {    # child
+        close STDIN;
+        close STDOUT;
+        close STDERR;
+       $self->debug('CHILD: start download');
+       $self->SUPER::_download($dlurl, $dlfile, $video);
+       $self->debug('CHILD: end download');
+       exit;
+       $self->debug('CHILD: AFTER EXIT? WTF!');
     }
 
     return 1;
 }
     }
 
     return 1;
 }
+