From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <gentoo-commits+bounces-1189859-garchives=archives.gentoo.org@lists.gentoo.org>
Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by finch.gentoo.org (Postfix) with ESMTPS id E5AB4138359
	for <garchives@archives.gentoo.org>; Wed, 22 Jul 2020 17:47:03 +0000 (UTC)
Received: from pigeon.gentoo.org (localhost [127.0.0.1])
	by pigeon.gentoo.org (Postfix) with SMTP id 05FD9E093B;
	Wed, 22 Jul 2020 17:47:03 +0000 (UTC)
Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by pigeon.gentoo.org (Postfix) with ESMTPS id CB548E093B
	for <gentoo-commits@lists.gentoo.org>; Wed, 22 Jul 2020 17:47:02 +0000 (UTC)
Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84])
	(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
	(No client certificate requested)
	by smtp.gentoo.org (Postfix) with ESMTPS id 35F8234EE1C
	for <gentoo-commits@lists.gentoo.org>; Wed, 22 Jul 2020 17:47:01 +0000 (UTC)
Received: from localhost.localdomain (localhost [IPv6:::1])
	by oystercatcher.gentoo.org (Postfix) with ESMTP id 14DC22D3
	for <gentoo-commits@lists.gentoo.org>; Wed, 22 Jul 2020 17:46:55 +0000 (UTC)
From: "Zac Medico" <zmedico@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Content-Transfer-Encoding: 8bit
Content-type: text/plain; charset=UTF-8
Reply-To: gentoo-dev@lists.gentoo.org, "Zac Medico" <zmedico@gentoo.org>
Message-ID: <1595436933.3561071e07ad47db91bf0f2c2c2b02e2061b217c.zmedico@gentoo>
Subject: [gentoo-commits] proj/portage:master commit in: lib/portage/dbapi/
X-VCS-Repository: proj/portage
X-VCS-Files: lib/portage/dbapi/_MergeProcess.py
X-VCS-Directories: lib/portage/dbapi/
X-VCS-Committer: zmedico
X-VCS-Committer-Name: Zac Medico
X-VCS-Revision: 3561071e07ad47db91bf0f2c2c2b02e2061b217c
X-VCS-Branch: master
Date: Wed, 22 Jul 2020 17:46:55 +0000 (UTC)
Precedence: bulk
List-Post: <mailto:gentoo-commits@lists.gentoo.org>
List-Help: <mailto:gentoo-commits+help@lists.gentoo.org>
List-Unsubscribe: <mailto:gentoo-commits+unsubscribe@lists.gentoo.org>
List-Subscribe: <mailto:gentoo-commits+subscribe@lists.gentoo.org>
List-Id: Gentoo Linux mail <gentoo-commits.gentoo.org>
X-BeenThere: gentoo-commits@lists.gentoo.org
X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply
X-Archives-Salt: 3b81d2b4-3cbf-4d0f-9de5-f7265be27d8a
X-Archives-Hash: 65472a30aa6d478d60601059a4cb5f35

commit:     3561071e07ad47db91bf0f2c2c2b02e2061b217c
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Sun Jul 19 06:31:37 2020 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Wed Jul 22 16:55:33 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=3561071e

MergeProcess: replace os.fork with multiprocessing.Process (bug 730192)

Fix the MergeProcess _spawn method to call the superclass _spawn
method, in order to replace os.fork with multiprocessing.Process,
promoting a healthy state for the forked interpreter.

Bug: https://bugs.gentoo.org/730192
Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>

 lib/portage/dbapi/_MergeProcess.py | 106 +++++++++++--------------------------
 1 file changed, 30 insertions(+), 76 deletions(-)

diff --git a/lib/portage/dbapi/_MergeProcess.py b/lib/portage/dbapi/_MergeProcess.py
index 274ef586f..6924c8b0e 100644
--- a/lib/portage/dbapi/_MergeProcess.py
+++ b/lib/portage/dbapi/_MergeProcess.py
@@ -3,9 +3,6 @@
 
 import io
 import platform
-import signal
-import sys
-import traceback
 
 import fcntl
 import portage
@@ -24,7 +21,7 @@ class MergeProcess(ForkProcess):
 		'vartree', 'blockers', 'pkgloc', 'infloc', 'myebuild',
 		'mydbapi', 'postinst_failure', 'prev_mtimes', 'unmerge',
 		'_elog_reader_fd',
-		'_buf', '_elog_keys', '_locked_vdb')
+		'_buf', '_counter', '_dblink', '_elog_keys', '_locked_vdb')
 
 	def _start(self):
 		# Portage should always call setcpv prior to this
@@ -103,8 +100,8 @@ class MergeProcess(ForkProcess):
 
 	def _spawn(self, args, fd_pipes, **kwargs):
 		"""
-		Fork a subprocess, apply local settings, and call
-		dblink.merge(). TODO: Share code with ForkProcess.
+		Extend the superclass _spawn method to perform some pre-fork and
+		post-fork actions.
 		"""
 
 		elog_reader_fd, elog_writer_fd = os.pipe()
@@ -132,57 +129,31 @@ class MergeProcess(ForkProcess):
 		# FEATURES=parallel-install skips this lock in order to
 		# improve performance, and the risk is practically negligible.
 		self._lock_vdb()
-		counter = None
 		if not self.unmerge:
-			counter = self.vartree.dbapi.counter_tick()
-
-		parent_pid = os.getpid()
-		pid = None
-		try:
-			pid = os.fork()
-
-			if pid != 0:
-				if not isinstance(pid, int):
-					raise AssertionError(
-						"fork returned non-integer: %s" % (repr(pid),))
-
-				os.close(elog_writer_fd)
-				self._elog_reader_fd = elog_reader_fd
-				self._buf = ""
-				self._elog_keys = set()
-				# Discard messages which will be collected by the subprocess,
-				# in order to avoid duplicates (bug #446136).
-				portage.elog.messages.collect_messages(key=mylink.mycpv)
-
-				# invalidate relevant vardbapi caches
-				if self.vartree.dbapi._categories is not None:
-					self.vartree.dbapi._categories = None
-				self.vartree.dbapi._pkgs_changed = True
-				self.vartree.dbapi._clear_pkg_cache(mylink)
-
-				return [pid]
-
-			os.close(elog_reader_fd)
-
-			# Use default signal handlers in order to avoid problems
-			# killing subprocesses as reported in bug #353239.
-			signal.signal(signal.SIGINT, signal.SIG_DFL)
-			signal.signal(signal.SIGTERM, signal.SIG_DFL)
-
-			# Unregister SIGCHLD handler and wakeup_fd for the parent
-			# process's event loop (bug 655656).
-			signal.signal(signal.SIGCHLD, signal.SIG_DFL)
-			try:
-				wakeup_fd = signal.set_wakeup_fd(-1)
-				if wakeup_fd > 0:
-					os.close(wakeup_fd)
-			except (ValueError, OSError):
-				pass
-
-			portage.locks._close_fds()
-			# We don't exec, so use close_fds=False
-			# (see _setup_pipes docstring).
-			portage.process._setup_pipes(fd_pipes, close_fds=False)
+			self._counter = self.vartree.dbapi.counter_tick()
+
+		self._dblink = mylink
+		self._elog_reader_fd = elog_reader_fd
+		pids = super(MergeProcess, self)._spawn(args, fd_pipes, **kwargs)
+		os.close(elog_writer_fd)
+		self._buf = ""
+		self._elog_keys = set()
+		# Discard messages which will be collected by the subprocess,
+		# in order to avoid duplicates (bug #446136).
+		portage.elog.messages.collect_messages(key=mylink.mycpv)
+
+		# invalidate relevant vardbapi caches
+		if self.vartree.dbapi._categories is not None:
+			self.vartree.dbapi._categories = None
+		self.vartree.dbapi._pkgs_changed = True
+		self.vartree.dbapi._clear_pkg_cache(mylink)
+
+		return pids
+
+	def _run(self):
+			os.close(self._elog_reader_fd)
+			counter = self._counter
+			mylink = self._dblink
 
 			portage.output.havecolor = self.settings.get('NOCOLOR') \
 				not in ('yes', 'true')
@@ -207,8 +178,7 @@ class MergeProcess(ForkProcess):
 			self.settings.backup_changes("PORTAGE_BACKGROUND")
 
 			rval = 1
-			try:
-				if self.unmerge:
+			if self.unmerge:
 					if not mylink.exists():
 						rval = os.EX_OK
 					elif mylink.unmerge(
@@ -219,27 +189,11 @@ class MergeProcess(ForkProcess):
 						finally:
 							mylink.unlockdb()
 						rval = os.EX_OK
-				else:
+			else:
 					rval = mylink.merge(self.pkgloc, self.infloc,
 						myebuild=self.myebuild, mydbapi=self.mydbapi,
 						prev_mtimes=self.prev_mtimes, counter=counter)
-			except SystemExit:
-				raise
-			except:
-				traceback.print_exc()
-				# os._exit() skips stderr flush!
-				sys.stderr.flush()
-			finally:
-				os._exit(rval)
-
-		finally:
-			if pid == 0 or (pid is None and os.getpid() != parent_pid):
-				# Call os._exit() from a finally block in order
-				# to suppress any finally blocks from earlier
-				# in the call stack (see bug #345289). This
-				# finally block has to be setup before the fork
-				# in order to avoid a race condition.
-				os._exit(1)
+			return rval
 
 	def _async_waitpid_cb(self, *args, **kwargs):
 		"""