1 #----------------------------------------------------------------------
2 # Monkeysphere Validation Agent, Perl version
3 # Marginal User Interface for reasonable prompting
4 # Copyright © 2010 Daniel Kahn Gillmor <dkg@fifthhorseman.net>,
5 # Matthew James Goins <mjgoins@openflows.com>,
6 # Jameson Graef Rollins <jrollins@finestructure.net>,
7 # Elliot Winard <enw@caveteen.com>
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #----------------------------------------------------------------------
24 { package Crypt::Monkeysphere::MSVA::Monitor;
26 use Module::Load::Conditional;
35 $self->{dialog} = Gtk2::Dialog->new("Monkeysphere Validation Agent updated!",
41 my $icon_file = '/usr/share/pixmaps/monkeysphere-icon.png';
43 $self->{dialog}->set_default_icon_from_file($icon_file)
45 $self->{dialog}->set_default_response('ok');
46 my $label = Gtk2::Label->new("Some components of the running Monkeysphere
47 Validation Agent have been updated.
49 Would you like to restart the validation agent?");
51 $self->{dialog}->get_content_area()->add($label);
52 $self->{dialog}->signal_connect(response => sub { my ($dialog,$resp) = @_; $self->button_clicked($resp); });
53 $self->{dialog}->signal_connect(delete_event => sub { $self->button_clicked('cancel'); return 1; });
60 # if the user wants to restart the validation agent, we should terminate
61 # so that our parent gets a SIGCHLD.
64 $self->{dialog}->hide();
70 $self->{dialog}->show();
75 if (! Module::Load::Conditional::can_load('modules' => { 'Gtk2' => undef,
77 'Linux::Inotify2' => undef,
79 $self->{logger}->log('info', "Not spawning a monitoring process; issue 'kill -s HUP %d' to restart after upgrades.\nInstall Perl modules Gtk2, AnyEvent, and Linux::Inotify2 for automated restarts on upgrades.\n", $$);
83 if (! defined $fork) {
84 $self->{logger}->log('error', "Failed to spawn monitoring process\n");
88 $self->{monitorpid} = $fork;
89 $self->{logger}->log('debug', "spawned monitoring process pid %d\n", $self->{monitorpid});
99 $0 = 'MSVA (perl) Upgrade Monitor';
101 $self->{files} = [ $0, values(%INC) ];
102 $self->{logger}->log('debug3', "setting up monitoring on these files:\n%s\n", join("\n", @{$self->{files}}));
104 # close all filedescriptors except for std{in,out,err}:
105 # see http://markmail.org/message/mlbnvfa7ds25az2u
106 close $_ for map { /^(?:ARGV|std(?:err|out|in)|STD(?:ERR|OUT|IN))$/ ? () : *{$::{$_}}{IO} || () } keys %::;
108 $self->createwindow();
110 require Linux::Inotify2;
112 $self->{inotify} = Linux::Inotify2::->new()
113 or die "unable to create new inotify object: $!";
116 # FIXME: couldn't figure out how to get these to work in "strict subs" mode:
117 # my $flags = Linux::Inotify2::IN_MODIFY |
118 # Linux::Inotify2::IN_ATTRIB |
119 # Linux::Inotify2::IN_DELETE_SELF |
120 # Linux::Inotify2::IN_MOVE_SELF;
122 foreach my $file (@{$self->{files}}) {
123 $self->{inotify}->watch($file,
131 my $inotify_w = AnyEvent->io (
132 fh => $self->{inotify}->fileno,
134 cb => sub { $self->changed },
136 my $w = AnyEvent->signal(signal => 'TERM', cb => sub { exit 1; });
139 $self->{logger}->log('error', "Got to the end of the monitor process somehow\n");
140 # if we get here, we want to terminate with non-zero
148 $self->{logger}->log('debug', "changed!\n");
149 $self->{inotify}->poll();
152 # forget about cleaning up the monitoring child (e.g. we only want
153 # the parent process to know about this)
156 undef $self->{monitorpid};
161 return $self->{monitorpid};
166 if (defined $self->{monitorpid}) {
167 kill('TERM', $self->{monitorpid});
169 waitpid($self->{monitorpid}, 0);
171 undef($self->{monitorpid});
179 my $self = { monitorpid => undef,
183 bless ($self, $class);