[elbe-devel] [PATCH] pbuilder: add --cpuset option to "elbe pbuilder build" and "elbe control"

Torben Hohn torben.hohn at linutronix.de
Mon May 14 17:12:49 CEST 2018


qemu-user and java make problems with the current version of qemu
that is used.

-------------------------------------------------------------------------
qemu: uncaught target signal 6 (Aborted) - core dumped
/var/lib/dpkg/info/ca-certificates-java.postinst: line 43:

25111 Done                    find /etc/ssl/certs -name \*.pem
25113 Broken pipe             | while read filename; do
     alias=$(basename $filename .pem | tr A-Z a-z | tr -cs
              a-z0-9 _); alias=${alias%*_}; if [ -n "$FIXOLD" ]; then
         echo "-${alias}"; echo "-${alias}_pem";
     fi; echo "+${filename}";
 done
      25115 Aborted                 | java -Xmx64m -jar $JAR -storepass "$storepass"
 dpkg: error processing package ca-certificates-java (--configure):

 subprocess installed post-installation script returned error exit status 134
-------------------------------------------------------------------------

this seems to be an incarnation of this bug:
https://bugs.linaro.org/show_bug.cgi?id=3259

It seems to be fixed in a new qemu version. But upgrading to that version
is not so easy. Another possible mitigation is using only a single cpu.
In the past we used SMP=1 in the initvm Makefile for these kind of fixes.

Add an option that reduces the number of cpus using "taskset" per pbuild.
And put the necessary infrastructure in place to push the parameter down to
where it is evaluated.

This allows us to have a workaround in place for all classes of qemu-user
bugs with multithreading.

Signed-off-by: Torben Hohn <torben.hohn at linutronix.de>
---
 docs/elbe-pbuilder.txt         | 14 ++++++++++++++
 elbepack/asyncworker.py        |  5 +++--
 elbepack/commands/control.py   |  3 +++
 elbepack/commands/pbuilder.py  |  3 +++
 elbepack/daemons/soap/esoap.py |  6 +++---
 elbepack/elbeproject.py        | 22 +++++++++++++++++-----
 elbepack/pbuilderaction.py     |  4 ++--
 elbepack/projectmanager.py     |  4 ++--
 elbepack/soapclient.py         |  2 +-
 9 files changed, 48 insertions(+), 15 deletions(-)

diff --git a/docs/elbe-pbuilder.txt b/docs/elbe-pbuilder.txt
index f08e2150..86c1a46a 100644
--- a/docs/elbe-pbuilder.txt
+++ b/docs/elbe-pbuilder.txt
@@ -37,6 +37,12 @@ OPTIONS
 	This file is used to create a new ELBE project including the pbuilder
 	environment.
 
+--cpuset <int>::
+	When this value is not -1 (the default), the pbuilder is run using
+	'taskset <cpuset>' which allows to limit the number of cpus used
+	for the build. This is usefule when multithreading and qemu-user
+	yield problem with e.g. java.
+
 COMMANDS
 --------
 
@@ -71,6 +77,14 @@ EXAMPLES
 # elbe pbuilder build --project `cat ../myarm.prj`
 --------
 
+* Use the pbuilder we have built, to build 'program', using the prj
+  File generated in parent directory. And dont use more than one CPU
+  as a workaround for qemu-user and java problems.
++
+--------
+# cd program
+# elbe pbuilder build --project `cat ../myarm.prj` --cpuset 1
+--------
 
 SEE ALSO
 --------
diff --git a/elbepack/asyncworker.py b/elbepack/asyncworker.py
index 596e766a..75be989c 100644
--- a/elbepack/asyncworker.py
+++ b/elbepack/asyncworker.py
@@ -186,8 +186,9 @@ class BuildJob(AsyncWorkerJob):
 
 
 class PdebuildJob(AsyncWorkerJob):
-    def __init__(self, project):
+    def __init__(self, project, cpuset=-1):
         AsyncWorkerJob.__init__(self, project)
+        self.cpuset=cpuset
 
     def enqueue(self, queue, db):
         db.set_busy(self.project.builddir,
@@ -199,7 +200,7 @@ class PdebuildJob(AsyncWorkerJob):
     def execute(self, db):
         try:
             self.project.log.printo("Pdebuild started")
-            self.project.pdebuild()
+            self.project.pdebuild(self.cpuset)
             db.update_project_files(self.project)
             self.project.log.printo("Pdeb finished successfully")
             db.reset_busy(self.project.builddir, "build_done")
diff --git a/elbepack/commands/control.py b/elbepack/commands/control.py
index 39349f98..90c4b6a3 100644
--- a/elbepack/commands/control.py
+++ b/elbepack/commands/control.py
@@ -73,6 +73,9 @@ def run_command(argv):
                        dest="pbuilder_only", default=False,
                        help="Only list/download pbuilder Files")
 
+    oparser.add_option("--cpuset", default=-1, type="int",
+                       help="Limit cpuset of pbuilder commands (bitmask) (defaults to -1 for all CPUs)")
+
     devel = OptionGroup(
         oparser,
         "options for elbe developers",
diff --git a/elbepack/commands/pbuilder.py b/elbepack/commands/pbuilder.py
index d3adb48a..1a806c67 100644
--- a/elbepack/commands/pbuilder.py
+++ b/elbepack/commands/pbuilder.py
@@ -38,6 +38,9 @@ def run_command(argv):
     oparser.add_option("--output", dest="outdir", default=None,
                        help="directory where to save downloaded Files")
 
+    oparser.add_option("--cpuset", default=-1, type="int",
+                       help="Limit cpuset of pbuilder commands (bitmask) (defaults to -1 for all CPUs)")
+
     (opt, args) = oparser.parse_args(argv)
 
     if len(args) < 1:
diff --git a/elbepack/daemons/soap/esoap.py b/elbepack/daemons/soap/esoap.py
index 83bae9f1..a42cef7a 100644
--- a/elbepack/daemons/soap/esoap.py
+++ b/elbepack/daemons/soap/esoap.py
@@ -234,12 +234,12 @@ class ESoap (ServiceBase):
         fp.write(binascii.a2b_base64(data))
         fp.close()
 
-    @rpc(String)
+    @rpc(String, Integer)
     @authenticated_uid
     @soap_faults
-    def finish_pdebuild(self, uid, builddir):
+    def finish_pdebuild(self, uid, builddir, cpuset):
         self.app.pm.open_project(uid, builddir)
-        self.app.pm.build_current_pdebuild(uid)
+        self.app.pm.build_current_pdebuild(uid, cpuset)
 
     @rpc(String, String)
     @authenticated_uid
diff --git a/elbepack/elbeproject.py b/elbepack/elbeproject.py
index f2c8fa9f..de188d03 100644
--- a/elbepack/elbeproject.py
+++ b/elbepack/elbeproject.py
@@ -330,7 +330,8 @@ class ElbeProject (object):
         else:
             self.log.printo("unknown pbuild source vcs: %s" % p.tag)
 
-        self.pdebuild_build()
+        # pdebuild_build(-1) means use all cpus
+        self.pdebuild_build(cpuset=-1)
 
     def build(self, skip_debootstrap=False, build_bin=False,
               build_sources=False, cdrom_size=None, debug=False,
@@ -538,7 +539,7 @@ class ElbeProject (object):
         self.log.do('mkdir -p "%s"' % os.path.join(self.builddir,
                                                    "pbuilder", "result"))
 
-    def pdebuild(self):
+    def pdebuild(self, cpuset):
         self.pdebuild_init()
 
         pbdir = os.path.join(self.builddir, "pdebuilder", "current")
@@ -562,17 +563,28 @@ class ElbeProject (object):
                 "current_pdebuild.tar.gz"),
                 pbdir))
 
-        self.pdebuild_build()
+        self.pdebuild_build(cpuset)
         self.repo.finalize()
 
-    def pdebuild_build(self):
+    def pdebuild_build(self, cpuset):
+        # check whether we have to use taskset to run pdebuild
+        # this might be useful, when things like java dont
+        # work with multithreading
+        #
+        if cpuset!=-1:
+            cpuset_cmd = 'taskset %d ' % cpuset
+        else:
+            # cpuset == -1 means empty cpuset_cmd
+            cpuset_cmd = ''
+
         try:
-            self.log.do('cd "%s"; pdebuild --debbuildopts "-j%s -sa" '
+            self.log.do('cd "%s"; %s pdebuild --debbuildopts "-j%s -sa" '
                         '--configfile "%s" '
                         '--use-pdebuild-internal --buildresult "%s"' % (
                             os.path.join(self.builddir,
                                          "pdebuilder",
                                          "current"),
+                            cpuset_cmd,
                             cfg['pbuilder_jobs'],
                             os.path.join(self.builddir, "pbuilderrc"),
                             os.path.join(self.builddir, "pbuilder", "result")))
diff --git a/elbepack/pbuilderaction.py b/elbepack/pbuilderaction.py
index 7806b945..4058356c 100644
--- a/elbepack/pbuilderaction.py
+++ b/elbepack/pbuilderaction.py
@@ -227,8 +227,8 @@ class BuildAction(PBuilderAction):
         print("")
 
         try:
-            system('%s control set_pdebuild "%s" "%s"' %
-                   (elbe_exe, prjdir, tmp.fname("pdebuild.tar.gz")))
+            system('%s control set_pdebuild --cpuset "%d" "%s" "%s"' %
+                   (elbe_exe, opt.cpuset, prjdir, tmp.fname("pdebuild.tar.gz")))
         except CommandError:
             print("elbe control set_pdebuild Failed", file=sys.stderr)
             print("Giving up", file=sys.stderr)
diff --git a/elbepack/projectmanager.py b/elbepack/projectmanager.py
index 721f5591..60d76659 100644
--- a/elbepack/projectmanager.py
+++ b/elbepack/projectmanager.py
@@ -311,14 +311,14 @@ class ProjectManager(object):
             ep = self._get_current_project(userid, allow_busy=False)
             self.worker.enqueue(CreatePbuilderJob(ep))
 
-    def build_current_pdebuild(self, userid):
+    def build_current_pdebuild(self, userid, cpuset):
         with self.lock:
             ep = self._get_current_project(userid, allow_busy=False)
             if not path.isdir(path.join(ep.builddir, "pbuilder")):
                 raise InvalidState('No pbuilder exists: run "elbe pbuilder '
                                    'create --project %s" first' % ep.builddir)
 
-            self.worker.enqueue(PdebuildJob(ep))
+            self.worker.enqueue(PdebuildJob(ep, cpuset))
 
     def set_orig_fname(self, userid, fname):
         with self.lock:
diff --git a/elbepack/soapclient.py b/elbepack/soapclient.py
index 7b35a7d2..f91081a9 100644
--- a/elbepack/soapclient.py
+++ b/elbepack/soapclient.py
@@ -686,7 +686,7 @@ class SetPdebuilderAction(ClientAction):
             if len(bindata) != size:
                 break
 
-        client.service.finish_pdebuild(builddir)
+        client.service.finish_pdebuild(builddir, opt.cpuset)
 
 
 ClientAction.register(SetPdebuilderAction)
-- 
2.11.0




More information about the elbe-devel mailing list