Module: tools
Branch: master
Commit: fc96df4c171a80dc1df960c44d9c8734d987348c
URL: http://source.winehq.org/git/tools.git/?a=commit;h=fc96df4c171a80dc1df960c4…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Mon Oct 16 03:43:19 2017 +0200
testbot: Better avoid race conditions in VMs::RunRevert().
In order to use LibvirtTool for more than reverts, avoiding race
conditions cannot rely on the special relationship between
Status=reverting and ChildPid. So avoid the race conditions the right
way in VMs::RunRevert().
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/lib/WineTestBot/VMs.pm | 97 ++++++++++++++++++++++++++++++++----------
1 file changed, 75 insertions(+), 22 deletions(-)
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index 629d408..86dee6c 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -142,6 +142,8 @@ are undergoing maintenance.
=cut
+use File::Basename;
+
use ObjectModel::BackEnd;
use WineTestBot::Config;
use WineTestBot::Engine::Notify;
@@ -309,38 +311,89 @@ sub RunRevert($)
{
my ($self) = @_;
- $self->Status("reverting");
- my ($ErrProperty, $ErrMessage) = $self->Save();
- return $ErrMessage if (defined $ErrMessage);
-
- # Make sure the child process does not inherit the database connection
+ my $Tool = "LibvirtTool.pl";
+ my $Args = ["$BinDir/$Tool", "--log-only", "revert", $self->GetKey()];
+
+ # There are two $VM->ChildPid race conditions to avoid:
+ # - Between the child process and new calls to ScheduleJobs().
+ # We cannot leave setting ChildPid to the child process because then it
+ # may still not be set by the time the next ScheduleJobs() call happens,
+ # which would result in a new child being started.
+ # Note that the status is not guaranteed to change in _RunVMTool() so it
+ # cannot be relied on to avoid this race.
+ # - Between RunRevert() and the exit of the child process.
+ # The child process may exit before RunRevert() gets around to setting
+ # ChildPid after the fork(). This would result in ChildPid remaining set
+ # indefinitely.
+ # So set ChildPid in the parent and synchronize with the child so it only
+ # starts once this is done.
+
+ # Make sure the child process will use its own database connection
$self->GetBackEnd()->Close();
- my $Pid = fork;
+ use Fcntl;
+ my ($fd_read, $fd_write);
+ pipe($fd_read, $fd_write); # For synchronization
+
+ my $Pid = fork();
if (!defined $Pid)
{
+ close($fd_read);
+ close($fd_write);
return "Unable to start child process: $!";
}
- elsif (!$Pid)
+ if ($Pid)
{
- $ENV{PATH} = "/usr/bin:/bin";
- delete $ENV{ENV};
- require WineTestBot::Log;
- WineTestBot::Log::SetupRedirects();
- exec("$BinDir/LibvirtTool.pl", "--log-only", "revert", $self->GetKey()) or
- WineTestBot::Log::LogMsg("Unable to exec LibvirtTool.pl: $!\n");
- exit(1);
+ close($fd_read);
+
+ # Set the Status and ChildPid
+ $self->Status("reverting");
+ $self->ChildPid($Pid);
+ my ($ErrProperty, $ErrMessage) = $self->Save();
+ if ($ErrMessage)
+ {
+ close($fd_write);
+ return "Could not set the $Tool pid: $ErrMessage ($ErrProperty)";
+ }
+
+ # Let the child go
+ close($fd_write);
+
+ return undef;
}
- # Note that if the child process completes quickly (typically due to some
- # error), it may set ChildPid to undef before we get here. So we may end up
- # with non-reverting VMs for which ChildPid is set. That's ok because
- # ChildPid should be ignored anyway if Status is not 'reverting' or
- # 'sleeping'.
- $self->ChildPid($Pid);
- $self->Save();
+ # Wait for the parent to set $VM->ChildPid
+ close($fd_write);
+ sysread($fd_read, $fd_write, 1);
+ close($fd_read);
+
+ # Get up-to-date information on the VM and verify the pid. If the parent
+ # failed to set the pid it may try to start another process at any time.
+ # So abort in order avoid interference.
+ require WineTestBot::VMs;
+ my $VM = WineTestBot::VMs::CreateVMs()->GetItem($self->GetKey());
+ exit 1 if (($VM->ChildPid || 0) != $$);
+ $self->GetBackEnd()->Close();
+
+ require WineTestBot::Log;
+ WineTestBot::Log::LogMsg("Starting child: @$Args\n");
+
+ # Set up the file descriptors for the new process
+ WineTestBot::Log::SetupRedirects();
+
+ $ENV{PATH} = "/usr/bin:/bin";
+ exec(@$Args) or
+ WineTestBot::Log::LogMsg("Unable to exec $Tool: $!\n");
- return undef;
+ # Reset the Status and ChildPid since the exec failed
+ $self->Status("offline");
+ $self->ChildPid(undef);
+ my ($ErrProperty, $ErrMessage) = $self->Save();
+ if ($ErrMessage)
+ {
+ WineTestBot::Log::LogMsg("Could not remove the $Tool pid: $ErrMessage ($ErrProperty)\n");
+ }
+ exit 1;
}
Module: tools
Branch: master
Commit: dfd3c1911f1befa6df35e6e327f936f1e07f4407
URL: http://source.winehq.org/git/tools.git/?a=commit;h=dfd3c1911f1befa6df35e6e3…
Author: Francois Gouget <fgouget(a)codeweavers.com>
Date: Mon Oct 16 03:43:12 2017 +0200
testbot: Add functions wrapping the VM::ChildPid field.
They allow checking if the VM status is compatible with having a child
process, checking if the VM has a running process and killing the VM's
child process if any.
This makes the relevant code more readable and more maintanable by
factorizing these operations.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
testbot/bin/Engine.pl | 18 +++++++--------
testbot/lib/WineTestBot/VMs.pm | 51 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/testbot/bin/Engine.pl b/testbot/bin/Engine.pl
index ee496e2..b9c6ceb 100755
--- a/testbot/bin/Engine.pl
+++ b/testbot/bin/Engine.pl
@@ -71,8 +71,8 @@ sub FatalError(@)
=item C<Cleanup()>
-The Cleanup() function gets the tasks and VMs in a consistent state on the
-Engine startup or cleanly stops the tasks and VMs on shutdown.
+The Cleanup() function gets the Tasks and VMs in a consistent state on the
+Engine startup or cleanly stops the Tasks and VMs on shutdown.
It has to contend with three main scenarios:
- The Engine being restarted. Any task started just before that is still
running should still have its process and powered on VM and should be left
@@ -81,15 +81,14 @@ It has to contend with three main scenarios:
- The Engine startup after a reboot. All task processes will be dead and need
to be requeued. But the VMs are likely to be hosted on a separate machine so
it is quite possible that they will still be running. Hopefully any running
- process matching a task's ChildPid will belong to another user so we don't
+ process matching a Task's ChildPid will belong to another user so we don't
mistake that case for the previous one.
-- A shutdown of the Engine and its tasks / VMs. In this case it's used to
+- A shutdown of the Engine and its Tasks / VMs. In this case it's used to
kill the running tasks and requeue them, and/or power off the VMs.
In all cases we only trust that a VM status field is still valid if:
-- It is 'running' and used by a task that is still running.
-- It is 'reverting' or 'sleeping', is powered on and the revert process is
- still running.
+- It is 'running' and used by a Task that is still running.
+- It can have a running process and that process is still running.
- It is 'idle' and powered on.
In all other cases the VM will be powered off and marked as such.
@@ -187,15 +186,14 @@ sub Cleanup(;$$)
{
if ($KillVMs)
{
- kill("TERM", $VM->ChildPid) if (defined $VM->ChildPid);
+ $VM->KillChild();
}
elsif ($VM->Status eq "idle")
{
# Assume these are still ready for use
next;
}
- elsif (($VM->Status eq "reverting" or $VM->Status eq "sleeping") and
- defined $VM->ChildPid and !kill(0, $VM->ChildPid))
+ elsif ($VM->CanHaveChild() and $VM->HasRunningChild())
{
# This VM is still being reverted. Let that process run its course.
LogMsg "$VMKey is being reverted\n";
diff --git a/testbot/lib/WineTestBot/VMs.pm b/testbot/lib/WineTestBot/VMs.pm
index af052d9..629d408 100644
--- a/testbot/lib/WineTestBot/VMs.pm
+++ b/testbot/lib/WineTestBot/VMs.pm
@@ -226,6 +226,57 @@ sub Status($;$)
return $NewStatus;
}
+=pod
+=over 12
+
+=item C<CanHaveChild()>
+
+Returns true if the VM status is compatible with ChildPid being set.
+
+=back
+=cut
+
+sub CanHaveChild($)
+{
+ my ($self) = @_;
+ return ($self->Status =~ /^(?:reverting|sleeping)$/);
+}
+
+=pod
+=over 12
+
+=item C<HasRunningChild()>
+
+Returns true if ChildPid is set and still identifies a running process.
+
+=back
+=cut
+
+sub HasRunningChild($)
+{
+ my ($self) = @_;
+ return undef if (!$self->ChildPid);
+ return kill(0, $self->ChildPid);
+}
+
+=pod
+=over 12
+
+=item C<KillChild()>
+
+If ChildPid is set, kills the corresponding process and unsets ChildPid.
+It is up to the caller to save the updated VM object.
+
+=back
+=cut
+
+sub KillChild($)
+{
+ my ($self) = @_;
+ kill("TERM", $self->ChildPid) if ($self->ChildPid);
+ $self->ChildPid(undef);
+}
+
sub Validate($)
{
my ($self) = @_;
Module: website
Branch: master
Commit: 8003a9b7de67821a6ee69b86035734b5c353cb00
URL: http://source.winehq.org/git/website.git/?a=commit;h=8003a9b7de67821a6ee69b…
Author: Alexandre Julliard <julliard(a)winehq.org>
Date: Sat Oct 14 01:44:25 2017 +0200
Wine release 2.19
Signed-off-by: Alexandre Julliard <julliard(a)winehq.org>
---
news/en/2017101401.xml | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/news/en/2017101401.xml b/news/en/2017101401.xml
new file mode 100644
index 0000000..d88a985
--- /dev/null
+++ b/news/en/2017101401.xml
@@ -0,0 +1,17 @@
+<news>
+<date>October 14, 2017</date>
+<title>Wine 2.19 Released</title>
+<body>
+<p> The Wine development release 2.19 is now available.</p>
+<p> <a href="{$root}/announce/2.19">What's new</a> in this release:
+<ul>
+ <li>Support for 32-bit float audio on Android.</li>
+ <li>Named pipes now fully handled by the Wine server.</li>
+ <li>Support for a new Microsoft root certificate.</li>
+ <li>More transform fixes in GdiPlus.</li>
+ <li>Some heap allocation optimizations.</li>
+ <li>Various bug fixes.</li>
+</ul>
+<p>The source is <a href="//dl.winehq.org/wine/source/2.x/wine-2.19.tar.xz">available now</a>.
+Binary packages are in the process of being built, and will appear soon at their respective <a href="{$root}/download">download locations</a>.
+</p></body></news>