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

Manuel Traut manuel.traut at linutronix.de
Tue May 15 14:32:12 CEST 2018


Hi Torben,

On Mon, May 14, 2018 at 05:12:49PM +0200, Torben Hohn wrote:
> 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>

Signed-off & Reviewed-by: Manuel Traut <manut at linutronix.de>

I'll integrate into devel/elbe-3.0. I think we will run in these kind of errors
again in the future, so this might be a useful workaround.

However if you want to build java i think SMP=1 is a bad idea..

> ---
>  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
> 
> 
> _______________________________________________
> elbe-devel mailing list
> elbe-devel at linutronix.de
> https://lists.linutronix.de/mailman/listinfo/elbe-devel



More information about the elbe-devel mailing list