From 9e07f3a45c1b321edd07530b278498cb09f8983c Mon Sep 17 00:00:00 2001
From: Zac Medico <zmedico@gentoo.org>
Date: Tue, 5 Jun 2018 20:14:41 -0700
Subject: [PATCH 1/2] _unlock_builddir_exit: fix cancel/returncode interaction

When the _unlock_builddir_exit returncode parameter has not been
specified, do not attempt to cancel the current task, since the
task has already completed. This mirrors logic added to the
Binpkg _unlock_builddir_exit method in the previous commit.

Fixes: 937d0156aa06 ("CompositeTask: handle SIGINT/TERM cancelled futures (bug 657436)")
Bug: https://bugs.gentoo.org/657436
---
 pym/_emerge/AbstractEbuildProcess.py | 8 ++++++--
 pym/_emerge/EbuildBuild.py           | 4 ++--
 pym/_emerge/PackageUninstall.py      | 4 ++--
 3 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py
index 370cac529d..af6429a006 100644
--- a/pym/_emerge/AbstractEbuildProcess.py
+++ b/pym/_emerge/AbstractEbuildProcess.py
@@ -412,7 +412,11 @@ def _async_unlock_builddir(self, returncode=None):
 
 	def _unlock_builddir_exit(self, unlock_future, returncode=None):
 		# Normally, async_unlock should not raise an exception here.
-		unlock_future.result()
+		unlock_future.cancelled() or unlock_future.result()
 		if returncode is not None:
-			self.returncode = returncode
+			if unlock_future.cancelled():
+				self.cancelled = True
+				self._was_cancelled()
+			else:
+				self.returncode = returncode
 			SpawnProcess._async_wait(self)
diff --git a/pym/_emerge/EbuildBuild.py b/pym/_emerge/EbuildBuild.py
index 8d264dd1cf..ab5a4da74b 100644
--- a/pym/_emerge/EbuildBuild.py
+++ b/pym/_emerge/EbuildBuild.py
@@ -354,12 +354,12 @@ def _async_unlock_builddir(self, returncode=None):
 
 	def _unlock_builddir_exit(self, unlock_task, returncode=None):
 		self._assert_current(unlock_task)
-		if unlock_task.cancelled:
+		if unlock_task.cancelled and returncode is not None:
 			self._default_final_exit(unlock_task)
 			return
 
 		# Normally, async_unlock should not raise an exception here.
-		unlock_task.future.result()
+		unlock_task.future.cancelled() or unlock_task.future.result()
 		if returncode is not None:
 			self.returncode = returncode
 			self._async_wait()
diff --git a/pym/_emerge/PackageUninstall.py b/pym/_emerge/PackageUninstall.py
index cb34130562..43210b4bc3 100644
--- a/pym/_emerge/PackageUninstall.py
+++ b/pym/_emerge/PackageUninstall.py
@@ -116,12 +116,12 @@ def _async_unlock_builddir(self, returncode=None):
 
 	def _unlock_builddir_exit(self, unlock_task, returncode=None):
 		self._assert_current(unlock_task)
-		if unlock_task.cancelled:
+		if unlock_task.cancelled and returncode is not None:
 			self._default_final_exit(unlock_task)
 			return
 
 		# Normally, async_unlock should not raise an exception here.
-		unlock_task.future.result()
+		unlock_task.future.cancelled() or unlock_task.future.result()
 		if returncode is not None:
 			self.returncode = returncode
 			self._async_wait()

From 1fc628eead43fa5da4b142479aa004ded8acceab Mon Sep 17 00:00:00 2001
From: Zac Medico <zmedico@gentoo.org>
Date: Tue, 5 Jun 2018 21:26:40 -0700
Subject: [PATCH 2/2] AbstractEbuildProcess: handle SIGINT during dir lock (bug
 657436)

When the build dir lock is interrupted by SIGINT/TERM, avoid raising
an unwanted CancelledError.

Bug: https://bugs.gentoo.org/657436
---
 pym/_emerge/AbstractEbuildProcess.py | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py
index af6429a006..bda0bd83f4 100644
--- a/pym/_emerge/AbstractEbuildProcess.py
+++ b/pym/_emerge/AbstractEbuildProcess.py
@@ -171,6 +171,13 @@ def _start_post_builddir_lock(self, lock_future=None, start_ipc_daemon=False):
 			if lock_future is not self._start_future:
 				raise AssertionError('lock_future is not self._start_future')
 			self._start_future = None
+			if lock_future.cancelled():
+				self._build_dir = None
+				self.cancelled = True
+				self._was_cancelled()
+				self._async_wait()
+				return
+
 			lock_future.result()
 
 		if start_ipc_daemon:
