source: main/trunk/greenstone2/perllib/cpan/Mojo/IOLoop/Subprocess.pm@ 32205

Last change on this file since 32205 was 32205, checked in by ak19, 6 years ago

First set of commits to do with implementing the new 'paged_html' output option of PDFPlugin that uses using xpdftools' new pdftohtml. So far tested only on Linux (64 bit), but things work there so I'm optimistically committing the changes since they work. 2. Committing the pre-built Linux binaries of XPDFtools for both 32 and 64 bit built by the XPDF group. 2. To use the correct bitness variant of xpdftools, setup.bash now exports the BITNESS env var, consulted by gsConvert.pl. 3. All the perl code changes to do with using xpdf tools' pdftohtml to generate paged_html and feed it in the desired form into GS(3): gsConvert.pl, PDFPlugin.pm and its parent ConvertBinaryPFile.pm have been modified to make it all work. xpdftools' pdftohtml generates a folder containing an html file and a screenshot for each page in a PDF (as well as an index.html linking to each page's html). However, we want a single html file that contains each individual 'page' html's content in a div, and need to do some further HTML style, attribute and structure modifications to massage the xpdftool output to what we want for GS. In order to parse and manipulate the HTML 'DOM' to do this, we're using the Mojo::DOM package that Dr Bainbridge found and which he's compiled up. Mojo::DOM is therefore also committed in this revision. Some further changes and some display fixes are required, but need to check with the others about that.

File size: 3.6 KB
Line 
1package Mojo::IOLoop::Subprocess;
2use Mojo::Base -base;
3
4use Carp 'croak';
5use Config;
6use Mojo::IOLoop;
7use Mojo::IOLoop::Stream;
8use POSIX ();
9use Storable;
10
11has deserialize => sub { \&Storable::thaw };
12has ioloop => sub { Mojo::IOLoop->singleton };
13has serialize => sub { \&Storable::freeze };
14
15sub pid { shift->{pid} }
16
17sub run {
18 my ($self, $child, $parent) = @_;
19
20 # No fork emulation support
21 croak 'Subprocesses do not support fork emulation' if $Config{d_pseudofork};
22
23 # Pipe for subprocess communication
24 pipe(my $reader, my $writer) or croak "Can't create pipe: $!";
25 $writer->autoflush(1);
26
27 # Child
28 croak "Can't fork: $!" unless defined(my $pid = $self->{pid} = fork);
29 unless ($pid) {
30 $self->ioloop->reset;
31 my $results = eval { [$self->$child] } || [];
32 print $writer $self->serialize->([$@, @$results]);
33 POSIX::_exit(0);
34 }
35
36 # Parent
37 my $me = $$;
38 my $stream = Mojo::IOLoop::Stream->new($reader)->timeout(0);
39 $self->ioloop->stream($stream);
40 my $buffer = '';
41 $stream->on(read => sub { $buffer .= pop });
42 $stream->on(
43 close => sub {
44 return unless $$ == $me;
45 waitpid $pid, 0;
46 my $results = eval { $self->deserialize->($buffer) } || [];
47 $self->$parent(shift(@$results) // $@, @$results);
48 }
49 );
50 return $self;
51}
52
531;
54
55=encoding utf8
56
57=head1 NAME
58
59Mojo::IOLoop::Subprocess - Subprocesses
60
61=head1 SYNOPSIS
62
63 use Mojo::IOLoop::Subprocess;
64
65 # Operation that would block the event loop for 5 seconds
66 my $subprocess = Mojo::IOLoop::Subprocess->new;
67 $subprocess->run(
68 sub {
69 my $subprocess = shift;
70 sleep 5;
71 return '♥', 'Mojolicious';
72 },
73 sub {
74 my ($subprocess, $err, @results) = @_;
75 say "Subprocess error: $err" and return if $err;
76 say "I $results[0] $results[1]!";
77 }
78 );
79
80 # Start event loop if necessary
81 $subprocess->ioloop->start unless $subprocess->ioloop->is_running;
82
83=head1 DESCRIPTION
84
85L<Mojo::IOLoop::Subprocess> allows L<Mojo::IOLoop> to perform computationally
86expensive operations in subprocesses, without blocking the event loop.
87
88=head1 ATTRIBUTES
89
90L<Mojo::IOLoop::Subprocess> implements the following attributes.
91
92=head2 deserialize
93
94 my $cb = $subprocess->deserialize;
95 $subprocess = $subprocess->deserialize(sub {...});
96
97A callback used to deserialize subprocess return values, defaults to using
98L<Storable>.
99
100 $subprocess->deserialize(sub {
101 my $bytes = shift;
102 return [];
103 });
104
105=head2 ioloop
106
107 my $loop = $subprocess->ioloop;
108 $subprocess = $subprocess->ioloop(Mojo::IOLoop->new);
109
110Event loop object to control, defaults to the global L<Mojo::IOLoop> singleton.
111
112=head2 serialize
113
114 my $cb = $subprocess->serialize;
115 $subprocess = $subprocess->serialize(sub {...});
116
117A callback used to serialize subprocess return values, defaults to using
118L<Storable>.
119
120 $subprocess->serialize(sub {
121 my $array = shift;
122 return '';
123 });
124
125=head1 METHODS
126
127L<Mojo::IOLoop::Subprocess> inherits all methods from L<Mojo::Base> and
128implements the following new ones.
129
130=head2 pid
131
132 my $pid = $subprocess->pid;
133
134Process id of the spawned subprocess if available.
135
136=head2 run
137
138 $subprocess = $subprocess->run(sub {...}, sub {...});
139
140Execute the first callback in a child process and wait for it to return one or
141more values, without blocking L</"ioloop"> in the parent process. Then execute
142the second callback in the parent process with the results. The return values of
143the first callback and exceptions thrown by it, will be serialized with
144L<Storable>, so they can be shared between processes.
145
146=head1 SEE ALSO
147
148L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
149
150=cut
Note: See TracBrowser for help on using the repository browser.