summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-12-30 01:33:10 -0800
committerZac Medico <zmedico@gentoo.org>2012-12-30 01:33:10 -0800
commit7ebb2f54877edb28621c33e380f8777b1b1dc201 (patch)
tree194c0a465f502258b82f43797db7f4c4b679408b
parent84139803585a9a415c6f94c765dadcdeb7592915 (diff)
downloadportage-7ebb2f54877edb28621c33e380f8777b1b1dc201.tar.gz
portage-7ebb2f54877edb28621c33e380f8777b1b1dc201.tar.bz2
portage-7ebb2f54877edb28621c33e380f8777b1b1dc201.zip
Use ctypes in subprocess for bug #448858.
Isolate ctypes usage in a subprocess, in order to avoid potential problems with stale cached libraries as described in bug #448858, comment #14 (also see http://bugs.python.org/issue14597).
-rw-r--r--pym/portage/dbapi/_SyncfsProcess.py53
-rw-r--r--pym/portage/dbapi/vartree.py47
2 files changed, 67 insertions, 33 deletions
diff --git a/pym/portage/dbapi/_SyncfsProcess.py b/pym/portage/dbapi/_SyncfsProcess.py
new file mode 100644
index 000000000..7518214ec
--- /dev/null
+++ b/pym/portage/dbapi/_SyncfsProcess.py
@@ -0,0 +1,53 @@
+# Copyright 2012 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage import os
+from portage.util._ctypes import find_library, LoadLibrary
+from portage.util._async.ForkProcess import ForkProcess
+
+class SyncfsProcess(ForkProcess):
+ """
+ Isolate ctypes usage in a subprocess, in order to avoid
+ potential problems with stale cached libraries as
+ described in bug #448858, comment #14 (also see
+ http://bugs.python.org/issue14597).
+ """
+
+ __slots__ = ('paths',)
+
+ @staticmethod
+ def _get_syncfs():
+
+ filename = find_library("c")
+ if filename is not None:
+ library = LoadLibrary(filename)
+ if library is not None:
+ try:
+ return library.syncfs
+ except AttributeError:
+ pass
+
+ return None
+
+ def _run(self):
+
+ syncfs_failed = False
+ syncfs = self._get_syncfs()
+
+ if syncfs is not None:
+ for path in self.paths:
+ try:
+ fd = os.open(path, os.O_RDONLY)
+ except OSError:
+ pass
+ else:
+ try:
+ if syncfs(fd) != 0:
+ # Happens with PyPy (bug #446610)
+ syncfs_failed = True
+ finally:
+ os.close(fd)
+
+ if syncfs is None or syncfs_failed:
+ return 1
+ return os.EX_OK
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 840e796f1..7a930e553 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -11,6 +11,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.data:portage_gid,portage_uid,secpass',
'portage.dbapi.dep_expand:dep_expand',
'portage.dbapi._MergeProcess:MergeProcess',
+ 'portage.dbapi._SyncfsProcess:SyncfsProcess',
'portage.dep:dep_getkey,isjustname,isvalidatom,match_from_list,' + \
'use_reduce,_get_slot_re,_slot_separator,_repo_separator',
'portage.eapi:_get_eapi_attrs',
@@ -29,7 +30,6 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.util.env_update:env_update',
'portage.util.listdir:dircache,listdir',
'portage.util.movefile:movefile',
- 'portage.util._ctypes:find_library,LoadLibrary',
'portage.util._dyn_libs.PreservedLibsRegistry:PreservedLibsRegistry',
'portage.util._dyn_libs.LinkageMapELF:LinkageMapELF@LinkageMap',
'portage.util._async.SchedulerInterface:SchedulerInterface',
@@ -4731,28 +4731,22 @@ class dblink(object):
"merge-sync" not in self.settings.features:
return
- syncfs_failed = False
- syncfs = _get_syncfs()
+ returncode = None
+ if platform.system() == "Linux":
- if syncfs is not None:
+ paths = []
for path in self._device_path_map.values():
- if path is False:
- continue
- try:
- fd = os.open(path, os.O_RDONLY)
- except OSError:
- pass
- else:
- try:
- if syncfs(fd) != 0:
- # Happens with PyPy (bug #446610)
- syncfs_failed = True
- except OSError:
- pass
- finally:
- os.close(fd)
+ if path is not False:
+ paths.append(path)
+ paths = tuple(paths)
+
+ proc = SyncfsProcess(paths=paths,
+ scheduler=(self._scheduler or
+ SchedulerInterface(EventLoop(main=False))))
+ proc.start()
+ returncode = proc.wait()
- if syncfs is None or syncfs_failed:
+ if returncode is None or returncode != os.EX_OK:
try:
proc = subprocess.Popen(["sync"])
except EnvironmentError:
@@ -4938,19 +4932,6 @@ class dblink(object):
finally:
self.unlockdb()
-def _get_syncfs():
- if platform.system() == "Linux":
- filename = find_library("c")
- if filename is not None:
- library = LoadLibrary(filename)
- if library is not None:
- try:
- return library.syncfs
- except AttributeError:
- pass
-
- return None
-
def merge(mycat, mypkg, pkgloc, infloc,
myroot=None, settings=None, myebuild=None,
mytree=None, mydbapi=None, vartree=None, prev_mtimes=None, blockers=None,