Récemment, toutes mes mises à jour système se sont mise à planter lors du téléchargement des sources par portage, quel que soit le miroir utilisé :
web ~ # emerge gdb
Calculating dependencies... done!
>>> Verifying ebuild manifests
>>> Emerging (1 of 1) sys-devel/gdb-7.0.1
>>> Downloading 'http://distfiles.gentoo.org/distfiles/gdb-7.0.1.tar.bz2'
>>> Downloading 'ftp://sources.redhat.com/pub/gdb/releases/gdb-7.0.1.tar.bz2'
>>> Downloading 'http://ftp.gnu.org/gnu/gdb/gdb-7.0.1.tar.bz2'
!!! Couldn't download 'gdb-7.0.1.tar.bz2'. Aborting.
* Fetch failed for 'sys-devel/gdb-7.0.1', Log file:
* '/var/tmp/portage/sys-devel/gdb-7.0.1/temp/build.log'
>>> Failed to emerge sys-devel/gdb-7.0.1, Log file:
>>> '/var/tmp/portage/sys-devel/gdb-7.0.1/temp/build.log'
* Messages for package sys-devel/gdb-7.0.1:
* Fetch failed for 'sys-devel/gdb-7.0.1', Log file:
* '/var/tmp/portage/sys-devel/gdb-7.0.1/temp/build.log'
Rien d'intéressant dans les logs, et le mode debug d'emerge n'apporte aucune information supplémentaire sur l'erreur de téléchargement. De plus, un wget manuel fonctionne parfaitement :
web ~ # wget http://distfiles.gentoo.org/distfiles/gdb-7.0.1.tar.bz2
--2010-10-13 18:47:22-- http://distfiles.gentoo.org/distfiles/gdb-7.0.1.tar.bz2
Resolving distfiles.gentoo.org... 130.239.17.6, 137.226.34.42
Connecting to distfiles.gentoo.org|130.239.17.6|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://mirrors.kernel.org/gentoo/distfiles/gdb-7.0.1.tar.bz2 [following]
--2010-10-13 18:47:22-- http://mirrors.kernel.org/gentoo/distfiles/gdb-7.0.1.tar.bz2
Resolving mirrors.kernel.org... 130.239.17.6, 199.6.1.174
Reusing existing connection to distfiles.gentoo.org:80.
HTTP request sent, awaiting response... 200 OK
Length: 17614682 (17M) [application/x-bzip2]
Saving to: `gdb-7.0.1.tar.bz2'
100%[===============================================================================================>] 17,614,682 4.66M/s in 3.9s
2010-10-13 18:47:27 (4.28 MB/s) - `gdb-7.0.1.tar.bz2' saved [17614682/17614682]
J'ai donc passé quelques heures à mettre des print un peu partout dans le code de portage, pour finalement déterminer que le script s'arrêtait violemment lors de l'appel à la fonction os.setgroups par la méthode _exec de process.py :
web ~ # head -380 /usr/lib/portage/pym/portage/process.py | tail -20
os.close(fd)
except OSError:
pass
# Set requested process permissions.
if gid:
os.setgid(gid)
if groups:
os.setgroups(groups)
if uid:
os.setuid(uid)
if umask:
os.umask(umask)
if pre_exec:
pre_exec()
# And switch to the new process.
os.execve(binary, myargs, env)
Un simple test permet de constater que la méthode os.setgroups() est en cause :
web ~ # python -c "import os; os.setgroups([250])"
Segmentation fault
Le workaround
Ce problème apparait lorsque emerge change son utlisateur et ses groupes avant le téléchargement. Un workaround simple est donc de désactiver cette fonctionalité, en ajoutant la ligne suivante dans le fichier /etc/make.conf :
FEATURES="-userfetch"
Cause et solution
Toutefois, ce problème est apparu récemment, et ne peut être reproduit sur mes autres installations Gentoo. J'ai donc repensé aux modifications que j'avais apportées récemment, et j'ai eu un déclic : j'ai réduit la taille de la pile pour optimiser la mémoire consommée par Apache !
J'avais donc réduit la taille de la pile de 8Mo à 256 ko. En essayant de l'augmenter un peu :
web ~ # ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 16120
max locked memory (kbytes, -l) 32
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 256
cpu time (seconds, -t) unlimited
max user processes (-u) 16120
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
web ~ # ulimit -s 512
web ~ # python -c "import os; os.setgroups([250])"
web ~ #
C'était donc bien la taille de la pile.
Visiblement ma modification dans le fichier /etc/conf.d/rc n'impactait pas uniquement le lancement des services comme je le pensais… J'ai donc changé la variable RC_ULIMIT :
RC_ULIMIT="-s 512"