[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