I: pbuilder: network access will be disabled during build I: Current time: Thu Mar 21 18:00:16 +14 2024 I: pbuilder-time-stamp: 1710993616 I: Building the build Environment I: extracting base tarball [/var/cache/pbuilder/unstable-reproducible-base.tgz] I: copying local configuration W: --override-config is not set; not updating apt.conf Read the manpage for details. I: mounting /proc filesystem I: mounting /sys filesystem I: creating /{dev,run}/shm I: mounting /dev/pts filesystem I: redirecting /dev/ptmx to /dev/pts/ptmx I: policy-rc.d already exists I: using eatmydata during job I: Copying source file I: copying [locust_2.24.0-1.dsc] I: copying [./locust_2.24.0.orig.tar.xz] I: copying [./locust_2.24.0-1.debian.tar.xz] I: Extracting source gpgv: Signature made Wed Mar 13 04:42:15 2024 gpgv: using RSA key B9FAD3192AF3E4A5309D9D39879F3C993801A94F gpgv: Can't check signature: No public key dpkg-source: warning: cannot verify inline signature for ./locust_2.24.0-1.dsc: no acceptable signature found dpkg-source: info: extracting locust in locust-2.24.0 dpkg-source: info: unpacking locust_2.24.0.orig.tar.xz dpkg-source: info: unpacking locust_2.24.0-1.debian.tar.xz I: using fakeroot in build. I: Installing the build-deps I: user script /srv/workspace/pbuilder/54022/tmp/hooks/D01_modify_environment starting debug: Running on ionos2-i386. I: Changing host+domainname to test build reproducibility I: Adding a custom variable just for the fun of it... I: Changing /bin/sh to bash '/bin/sh' -> '/bin/bash' lrwxrwxrwx 1 root root 9 Mar 21 04:00 /bin/sh -> /bin/bash I: Setting pbuilder2's login shell to /bin/bash I: Setting pbuilder2's GECOS to second user,second room,second work-phone,second home-phone,second other I: user script /srv/workspace/pbuilder/54022/tmp/hooks/D01_modify_environment finished I: user script /srv/workspace/pbuilder/54022/tmp/hooks/D02_print_environment starting I: set BASH=/bin/sh BASHOPTS=checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath BASH_ALIASES=() BASH_ARGC=() BASH_ARGV=() BASH_CMDS=() BASH_LINENO=([0]="12" [1]="0") BASH_LOADABLES_PATH=/usr/local/lib/bash:/usr/lib/bash:/opt/local/lib/bash:/usr/pkg/lib/bash:/opt/pkg/lib/bash:. BASH_SOURCE=([0]="/tmp/hooks/D02_print_environment" [1]="/tmp/hooks/D02_print_environment") BASH_VERSINFO=([0]="5" [1]="2" [2]="21" [3]="1" [4]="release" [5]="i686-pc-linux-gnu") BASH_VERSION='5.2.21(1)-release' BUILDDIR=/build/reproducible-path BUILDUSERGECOS='second user,second room,second work-phone,second home-phone,second other' BUILDUSERNAME=pbuilder2 BUILD_ARCH=i386 DEBIAN_FRONTEND=noninteractive DEB_BUILD_OPTIONS='buildinfo=+all reproducible=+all parallel=7 ' DIRSTACK=() DISTRIBUTION=unstable EUID=0 FUNCNAME=([0]="Echo" [1]="main") GROUPS=() HOME=/root HOSTNAME=i-capture-the-hostname HOSTTYPE=i686 HOST_ARCH=i386 IFS=' ' INVOCATION_ID=0e33ec4809f243669e6ad0eecc6d3ac0 LANG=C LANGUAGE=de_CH:de LC_ALL=C LD_LIBRARY_PATH=/usr/lib/libeatmydata LD_PRELOAD=libeatmydata.so MACHTYPE=i686-pc-linux-gnu MAIL=/var/mail/root OPTERR=1 OPTIND=1 OSTYPE=linux-gnu PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path PBCURRENTCOMMANDLINEOPERATION=build PBUILDER_OPERATION=build PBUILDER_PKGDATADIR=/usr/share/pbuilder PBUILDER_PKGLIBDIR=/usr/lib/pbuilder PBUILDER_SYSCONFDIR=/etc PIPESTATUS=([0]="0") POSIXLY_CORRECT=y PPID=54022 PS4='+ ' PWD=/ SHELL=/bin/bash SHELLOPTS=braceexpand:errexit:hashall:interactive-comments:posix SHLVL=3 SUDO_COMMAND='/usr/bin/timeout -k 24.1h 24h /usr/bin/ionice -c 3 /usr/bin/nice -n 11 /usr/bin/unshare --uts -- /usr/sbin/pbuilder --build --configfile /srv/reproducible-results/rbuild-debian/r-b-build.yq6ZqD0W/pbuilderrc_aX4y --distribution unstable --hookdir /etc/pbuilder/rebuild-hooks --debbuildopts -b --basetgz /var/cache/pbuilder/unstable-reproducible-base.tgz --buildresult /srv/reproducible-results/rbuild-debian/r-b-build.yq6ZqD0W/b2 --logfile b2/build.log locust_2.24.0-1.dsc' SUDO_GID=112 SUDO_UID=107 SUDO_USER=jenkins TERM=unknown TZ=/usr/share/zoneinfo/Etc/GMT-14 UID=0 USER=root _='I: set' http_proxy=http://78.137.99.97:3128 I: uname -a Linux i-capture-the-hostname 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64 GNU/Linux I: ls -l /bin lrwxrwxrwx 1 root root 7 Mar 20 07:44 /bin -> usr/bin I: user script /srv/workspace/pbuilder/54022/tmp/hooks/D02_print_environment finished -> Attempting to satisfy build-dependencies -> Creating pbuilder-satisfydepends-dummy package Package: pbuilder-satisfydepends-dummy Version: 0.invalid.0 Architecture: i386 Maintainer: Debian Pbuilder Team Description: Dummy package to satisfy dependencies with aptitude - created by pbuilder This package was created automatically by pbuilder to satisfy the build-dependencies of the package being currently built. Depends: debhelper-compat (= 13), pybuild-plugin-pyproject, python3-all, python3-configargparse (>= 1.5.5), python3-cryptography, python3-flask-cors, python3-flask-login (>= 0.6.3), python3-geventhttpclient (>= 2.0.8), python3-msgpack (>= 0.6.2), python3-psutil (>= 5.6.7), python3-pyquery (>= 1.4.3), python3-pytest, python3-requests (>= 2.9.1), python3-retry, python3-roundrobin, python3-setuptools, python3-typing-extensions, python3-zmq (>= 16.0.2) dpkg-deb: building package 'pbuilder-satisfydepends-dummy' in '/tmp/satisfydepends-aptitude/pbuilder-satisfydepends-dummy.deb'. Selecting previously unselected package pbuilder-satisfydepends-dummy. (Reading database ... 19645 files and directories currently installed.) Preparing to unpack .../pbuilder-satisfydepends-dummy.deb ... Unpacking pbuilder-satisfydepends-dummy (0.invalid.0) ... dpkg: pbuilder-satisfydepends-dummy: dependency problems, but configuring anyway as you requested: pbuilder-satisfydepends-dummy depends on debhelper-compat (= 13); however: Package debhelper-compat is not installed. pbuilder-satisfydepends-dummy depends on pybuild-plugin-pyproject; however: Package pybuild-plugin-pyproject is not installed. pbuilder-satisfydepends-dummy depends on python3-all; however: Package python3-all is not installed. pbuilder-satisfydepends-dummy depends on python3-configargparse (>= 1.5.5); however: Package python3-configargparse is not installed. pbuilder-satisfydepends-dummy depends on python3-cryptography; however: Package python3-cryptography is not installed. pbuilder-satisfydepends-dummy depends on python3-flask-cors; however: Package python3-flask-cors is not installed. pbuilder-satisfydepends-dummy depends on python3-flask-login (>= 0.6.3); however: Package python3-flask-login is not installed. pbuilder-satisfydepends-dummy depends on python3-geventhttpclient (>= 2.0.8); however: Package python3-geventhttpclient is not installed. pbuilder-satisfydepends-dummy depends on python3-msgpack (>= 0.6.2); however: Package python3-msgpack is not installed. pbuilder-satisfydepends-dummy depends on python3-psutil (>= 5.6.7); however: Package python3-psutil is not installed. pbuilder-satisfydepends-dummy depends on python3-pyquery (>= 1.4.3); however: Package python3-pyquery is not installed. pbuilder-satisfydepends-dummy depends on python3-pytest; however: Package python3-pytest is not installed. pbuilder-satisfydepends-dummy depends on python3-requests (>= 2.9.1); however: Package python3-requests is not installed. pbuilder-satisfydepends-dummy depends on python3-retry; however: Package python3-retry is not installed. pbuilder-satisfydepends-dummy depends on python3-roundrobin; however: Package python3-roundrobin is not installed. pbuilder-satisfydepends-dummy depends on python3-setuptools; however: Package python3-setuptools is not installed. pbuilder-satisfydepends-dummy depends on python3-typing-extensions; however: Package python3-typing-extensions is not installed. pbuilder-satisfydepends-dummy depends on python3-zmq (>= 16.0.2); however: Package python3-zmq is not installed. Setting up pbuilder-satisfydepends-dummy (0.invalid.0) ... Reading package lists... Building dependency tree... Reading state information... Initializing package states... Writing extended state information... Building tag database... pbuilder-satisfydepends-dummy is already installed at the requested version (0.invalid.0) pbuilder-satisfydepends-dummy is already installed at the requested version (0.invalid.0) The following NEW packages will be installed: autoconf{a} automake{a} autopoint{a} autotools-dev{a} bsdextrautils{a} ca-certificates{a} debhelper{a} dh-autoreconf{a} dh-python{a} dh-strip-nondeterminism{a} dwz{a} file{a} fonts-font-awesome{a} fonts-lato{a} gettext{a} gettext-base{a} groff-base{a} intltool-debian{a} libarchive-zip-perl{a} libbsd0{a} libc-ares2{a} libcom-err2t64{a} libdebhelper-perl{a} libelf1t64{a} libev4t64{a} libexpat1{a} libfile-stripnondeterminism-perl{a} libgssapi-krb5-2{a} libicu72{a} libjs-jquery{a} libjs-sphinxdoc{a} libjs-underscore{a} libk5crypto3{a} libkeyutils1{a} libkrb5-3{a} libkrb5support0{a} libmagic-mgc{a} libmagic1t64{a} libnorm1t64{a} libpgm-5.3-0t64{a} libpipeline1{a} libpython3-stdlib{a} libpython3.11-minimal{a} libpython3.11-stdlib{a} libpython3.12-minimal{a} libpython3.12-stdlib{a} libreadline8t64{a} libsodium23{a} libsub-override-perl{a} libtool{a} libuchardet0{a} libxml2{a} libxslt1.1{a} libzmq5{a} m4{a} man-db{a} media-types{a} netbase{a} openssl{a} po-debconf{a} pybuild-plugin-pyproject{a} python3{a} python3-all{a} python3-blinker{a} python3-brotli{a} python3-build{a} python3-certifi{a} python3-cffi-backend{a} python3-chardet{a} python3-charset-normalizer{a} python3-click{a} python3-colorama{a} python3-configargparse{a} python3-cryptography{a} python3-cssselect{a} python3-decorator{a} python3-distutils{a} python3-flask{a} python3-flask-cors{a} python3-flask-login{a} python3-gevent{a} python3-geventhttpclient{a} python3-greenlet{a} python3-idna{a} python3-iniconfig{a} python3-installer{a} python3-itsdangerous{a} python3-jinja2{a} python3-lib2to3{a} python3-lxml{a} python3-markupsafe{a} python3-minimal{a} python3-msgpack{a} python3-packaging{a} python3-pkg-resources{a} python3-pluggy{a} python3-psutil{a} python3-py{a} python3-pyproject-hooks{a} python3-pyquery{a} python3-pytest{a} python3-requests{a} python3-retry{a} python3-roundrobin{a} python3-setuptools{a} python3-six{a} python3-toml{a} python3-typing-extensions{a} python3-urllib3{a} python3-webob{a} python3-werkzeug{a} python3-wheel{a} python3-zmq{a} python3-zope.event{a} python3-zope.interface{a} python3.11{a} python3.11-minimal{a} python3.12{a} python3.12-minimal{a} readline-common{a} sensible-utils{a} sphinx-rtd-theme-common{a} tzdata{a} The following packages are RECOMMENDED but will NOT be installed: curl javascript-common krb5-locales libarchive-cpio-perl libltdl-dev libmail-sendmail-perl lynx python3-asgiref python3-babel python3-bs4 python3-dotenv python3-html5lib python3-openssl python3-pygments python3-pyinotify python3-simplejson wget 0 packages upgraded, 123 newly installed, 0 to remove and 0 not upgraded. Need to get 48.1 MB of archives. After unpacking 188 MB will be used. Writing extended state information... Get: 1 http://deb.debian.org/debian unstable/main i386 fonts-lato all 2.015-1 [2780 kB] Get: 2 http://deb.debian.org/debian unstable/main i386 libpython3.11-minimal i386 3.11.8-3 [816 kB] Get: 3 http://deb.debian.org/debian unstable/main i386 libexpat1 i386 2.6.2-1 [107 kB] Get: 4 http://deb.debian.org/debian unstable/main i386 python3.11-minimal i386 3.11.8-3 [1917 kB] Get: 5 http://deb.debian.org/debian unstable/main i386 python3-minimal i386 3.11.8-1 [26.3 kB] Get: 6 http://deb.debian.org/debian unstable/main i386 media-types all 10.1.0 [26.9 kB] Get: 7 http://deb.debian.org/debian unstable/main i386 netbase all 6.4 [12.8 kB] Get: 8 http://deb.debian.org/debian unstable/main i386 tzdata all 2024a-1 [255 kB] Get: 9 http://deb.debian.org/debian unstable/main i386 readline-common all 8.2-3.1 [69.2 kB] Get: 10 http://deb.debian.org/debian unstable/main i386 libreadline8t64 i386 8.2-3.1 [171 kB] Get: 11 http://deb.debian.org/debian unstable/main i386 libpython3.11-stdlib i386 3.11.8-3 [1794 kB] Get: 12 http://deb.debian.org/debian unstable/main i386 python3.11 i386 3.11.8-3 [597 kB] Get: 13 http://deb.debian.org/debian unstable/main i386 libpython3-stdlib i386 3.11.8-1 [9336 B] Get: 14 http://deb.debian.org/debian unstable/main i386 python3 i386 3.11.8-1 [27.4 kB] Get: 15 http://deb.debian.org/debian unstable/main i386 libpython3.12-minimal i386 3.12.2-4 [807 kB] Get: 16 http://deb.debian.org/debian unstable/main i386 python3.12-minimal i386 3.12.2-4 [2062 kB] Get: 17 http://deb.debian.org/debian unstable/main i386 sensible-utils all 0.0.22 [22.4 kB] Get: 18 http://deb.debian.org/debian unstable/main i386 openssl i386 3.1.5-1.1 [1246 kB] Get: 19 http://deb.debian.org/debian unstable/main i386 ca-certificates all 20240203 [158 kB] Get: 20 http://deb.debian.org/debian unstable/main i386 libmagic-mgc i386 1:5.45-3 [314 kB] Get: 21 http://deb.debian.org/debian unstable/main i386 libmagic1t64 i386 1:5.45-3 [114 kB] Get: 22 http://deb.debian.org/debian unstable/main i386 file i386 1:5.45-3 [42.9 kB] Get: 23 http://deb.debian.org/debian unstable/main i386 gettext-base i386 0.21-14+b1 [162 kB] Get: 24 http://deb.debian.org/debian unstable/main i386 libuchardet0 i386 0.0.8-1+b1 [69.1 kB] Get: 25 http://deb.debian.org/debian unstable/main i386 groff-base i386 1.23.0-3+b1 [1195 kB] Get: 26 http://deb.debian.org/debian unstable/main i386 bsdextrautils i386 2.39.3-10 [93.6 kB] Get: 27 http://deb.debian.org/debian unstable/main i386 libpipeline1 i386 1.5.7-1+b2 [39.6 kB] Get: 28 http://deb.debian.org/debian unstable/main i386 man-db i386 2.12.0-3 [1413 kB] Get: 29 http://deb.debian.org/debian unstable/main i386 m4 i386 1.4.19-4 [293 kB] Get: 30 http://deb.debian.org/debian unstable/main i386 autoconf all 2.71-3 [332 kB] Get: 31 http://deb.debian.org/debian unstable/main i386 autotools-dev all 20220109.1 [51.6 kB] Get: 32 http://deb.debian.org/debian unstable/main i386 automake all 1:1.16.5-1.3 [823 kB] Get: 33 http://deb.debian.org/debian unstable/main i386 autopoint all 0.21-14 [496 kB] Get: 34 http://deb.debian.org/debian unstable/main i386 libdebhelper-perl all 13.14.1 [85.6 kB] Get: 35 http://deb.debian.org/debian unstable/main i386 libtool all 2.4.7-7 [517 kB] Get: 36 http://deb.debian.org/debian unstable/main i386 dh-autoreconf all 20 [17.1 kB] Get: 37 http://deb.debian.org/debian unstable/main i386 libarchive-zip-perl all 1.68-1 [104 kB] Get: 38 http://deb.debian.org/debian unstable/main i386 libsub-override-perl all 0.10-1 [10.6 kB] Get: 39 http://deb.debian.org/debian unstable/main i386 libfile-stripnondeterminism-perl all 1.13.1-1 [19.4 kB] Get: 40 http://deb.debian.org/debian unstable/main i386 dh-strip-nondeterminism all 1.13.1-1 [8620 B] Get: 41 http://deb.debian.org/debian unstable/main i386 libelf1t64 i386 0.191-1 [194 kB] Get: 42 http://deb.debian.org/debian unstable/main i386 dwz i386 0.15-1+b1 [116 kB] Get: 43 http://deb.debian.org/debian unstable/main i386 libicu72 i386 72.1-4+b1 [9549 kB] Get: 44 http://deb.debian.org/debian unstable/main i386 libxml2 i386 2.9.14+dfsg-1.3+b2 [727 kB] Get: 45 http://deb.debian.org/debian unstable/main i386 gettext i386 0.21-14+b1 [1311 kB] Get: 46 http://deb.debian.org/debian unstable/main i386 intltool-debian all 0.35.0+20060710.6 [22.9 kB] Get: 47 http://deb.debian.org/debian unstable/main i386 po-debconf all 1.0.21+nmu1 [248 kB] Get: 48 http://deb.debian.org/debian unstable/main i386 debhelper all 13.14.1 [890 kB] Get: 49 http://deb.debian.org/debian unstable/main i386 python3-lib2to3 all 3.12.2-3 [77.6 kB] Get: 50 http://deb.debian.org/debian unstable/main i386 python3-distutils all 3.12.2-3 [131 kB] Get: 51 http://deb.debian.org/debian unstable/main i386 python3-pkg-resources all 68.1.2-2 [241 kB] Get: 52 http://deb.debian.org/debian unstable/main i386 python3-setuptools all 68.1.2-2 [468 kB] Get: 53 http://deb.debian.org/debian unstable/main i386 dh-python all 6.20240310 [106 kB] Get: 54 http://deb.debian.org/debian unstable/main i386 fonts-font-awesome all 5.0.10+really4.7.0~dfsg-4.1 [517 kB] Get: 55 http://deb.debian.org/debian unstable/main i386 libbsd0 i386 0.12.2-1 [134 kB] Get: 56 http://deb.debian.org/debian unstable/main i386 libc-ares2 i386 1.27.0-1 [156 kB] Get: 57 http://deb.debian.org/debian unstable/main i386 libcom-err2t64 i386 1.47.0-2.3+b1 [20.8 kB] Get: 58 http://deb.debian.org/debian unstable/main i386 libev4t64 i386 1:4.33-2.1 [44.0 kB] Get: 59 http://deb.debian.org/debian unstable/main i386 libkrb5support0 i386 1.20.1-6 [35.8 kB] Get: 60 http://deb.debian.org/debian unstable/main i386 libk5crypto3 i386 1.20.1-6 [83.0 kB] Get: 61 http://deb.debian.org/debian unstable/main i386 libkeyutils1 i386 1.6.3-3 [9432 B] Get: 62 http://deb.debian.org/debian unstable/main i386 libkrb5-3 i386 1.20.1-6 [359 kB] Get: 63 http://deb.debian.org/debian unstable/main i386 libgssapi-krb5-2 i386 1.20.1-6 [145 kB] Get: 64 http://deb.debian.org/debian unstable/main i386 libjs-jquery all 3.6.1+dfsg+~3.5.14-1 [326 kB] Get: 65 http://deb.debian.org/debian unstable/main i386 libjs-underscore all 1.13.4~dfsg+~1.11.4-3 [116 kB] Get: 66 http://deb.debian.org/debian unstable/main i386 libjs-sphinxdoc all 7.2.6-5 [150 kB] Get: 67 http://deb.debian.org/debian unstable/main i386 libnorm1t64 i386 1.5.9+dfsg-3.1 [237 kB] Get: 68 http://deb.debian.org/debian unstable/main i386 libpgm-5.3-0t64 i386 5.3.128~dfsg-2.1 [167 kB] Get: 69 http://deb.debian.org/debian unstable/main i386 libpython3.12-stdlib i386 3.12.2-4 [1889 kB] Get: 70 http://deb.debian.org/debian unstable/main i386 libsodium23 i386 1.0.18-1 [186 kB] Get: 71 http://deb.debian.org/debian unstable/main i386 libxslt1.1 i386 1.1.35-1 [253 kB] Get: 72 http://deb.debian.org/debian unstable/main i386 libzmq5 i386 4.3.5-1+b2 [306 kB] Get: 73 http://deb.debian.org/debian unstable/main i386 python3-packaging all 23.2-1 [44.8 kB] Get: 74 http://deb.debian.org/debian unstable/main i386 python3-pyproject-hooks all 1.0.0-2 [10.6 kB] Get: 75 http://deb.debian.org/debian unstable/main i386 python3-toml all 0.10.2-1 [16.2 kB] Get: 76 http://deb.debian.org/debian unstable/main i386 python3-wheel all 0.43.0-1 [52.5 kB] Get: 77 http://deb.debian.org/debian unstable/main i386 python3-build all 1.1.1-1 [32.5 kB] Get: 78 http://deb.debian.org/debian unstable/main i386 python3-installer all 0.7.0+dfsg1-2 [19.1 kB] Get: 79 http://deb.debian.org/debian unstable/main i386 pybuild-plugin-pyproject all 6.20240310 [10.9 kB] Get: 80 http://deb.debian.org/debian unstable/main i386 python3.12 i386 3.12.2-4 [653 kB] Get: 81 http://deb.debian.org/debian unstable/main i386 python3-all i386 3.11.8-1 [1056 B] Get: 82 http://deb.debian.org/debian unstable/main i386 python3-blinker all 1.7.0-1 [15.5 kB] Get: 83 http://deb.debian.org/debian unstable/main i386 python3-brotli i386 1.1.0-2+b3 [323 kB] Get: 84 http://deb.debian.org/debian unstable/main i386 python3-certifi all 2023.11.17-1 [155 kB] Get: 85 http://deb.debian.org/debian unstable/main i386 python3-cffi-backend i386 1.16.0-2+b1 [114 kB] Get: 86 http://deb.debian.org/debian unstable/main i386 python3-chardet all 5.2.0+dfsg-1 [107 kB] Get: 87 http://deb.debian.org/debian unstable/main i386 python3-charset-normalizer all 3.3.2-1 [51.6 kB] Get: 88 http://deb.debian.org/debian unstable/main i386 python3-colorama all 0.4.6-4 [36.2 kB] Get: 89 http://deb.debian.org/debian unstable/main i386 python3-click all 8.1.7-1 [94.0 kB] Get: 90 http://deb.debian.org/debian unstable/main i386 python3-configargparse all 1.7-1 [31.3 kB] Get: 91 http://deb.debian.org/debian unstable/main i386 python3-cryptography i386 42.0.5-2 [1272 kB] Get: 92 http://deb.debian.org/debian unstable/main i386 python3-cssselect all 1.2.0-2 [21.6 kB] Get: 93 http://deb.debian.org/debian unstable/main i386 python3-decorator all 5.1.1-5 [15.1 kB] Get: 94 http://deb.debian.org/debian unstable/main i386 python3-itsdangerous all 2.1.2-4 [17.1 kB] Get: 95 http://deb.debian.org/debian unstable/main i386 python3-markupsafe i386 2.1.5-1 [14.4 kB] Get: 96 http://deb.debian.org/debian unstable/main i386 python3-jinja2 all 3.1.3-1 [119 kB] Get: 97 http://deb.debian.org/debian unstable/main i386 python3-werkzeug all 3.0.1-3 [206 kB] Get: 98 http://deb.debian.org/debian unstable/main i386 python3-flask all 3.0.2-1 [104 kB] Get: 99 http://deb.debian.org/debian unstable/main i386 sphinx-rtd-theme-common all 2.0.0+dfsg-1 [1021 kB] Get: 100 http://deb.debian.org/debian unstable/main i386 python3-flask-cors all 4.0.0-1 [44.1 kB] Get: 101 http://deb.debian.org/debian unstable/main i386 python3-flask-login all 0.6.3-1 [22.5 kB] Get: 102 http://deb.debian.org/debian unstable/main i386 python3-greenlet i386 3.0.1-3 [181 kB] Get: 103 http://deb.debian.org/debian unstable/main i386 python3-zope.event all 5.0-0.1 [8164 B] Get: 104 http://deb.debian.org/debian unstable/main i386 python3-zope.interface i386 6.1-1 [153 kB] Get: 105 http://deb.debian.org/debian unstable/main i386 python3-gevent i386 23.9.1-1+b1 [1186 kB] Get: 106 http://deb.debian.org/debian unstable/main i386 python3-six all 1.16.0-6 [16.3 kB] Get: 107 http://deb.debian.org/debian unstable/main i386 python3-geventhttpclient i386 2.0.11-2 [42.4 kB] Get: 108 http://deb.debian.org/debian unstable/main i386 python3-idna all 3.6-2 [37.0 kB] Get: 109 http://deb.debian.org/debian unstable/main i386 python3-iniconfig all 1.1.1-2 [6396 B] Get: 110 http://deb.debian.org/debian unstable/main i386 python3-lxml i386 5.1.0-1 [2065 kB] Get: 111 http://deb.debian.org/debian unstable/main i386 python3-msgpack i386 1.0.3-3+b1 [101 kB] Get: 112 http://deb.debian.org/debian unstable/main i386 python3-pluggy all 1.4.0-1 [26.2 kB] Get: 113 http://deb.debian.org/debian unstable/main i386 python3-psutil i386 5.9.8-2 [226 kB] Get: 114 http://deb.debian.org/debian unstable/main i386 python3-py all 1.11.0-2 [88.7 kB] Get: 115 http://deb.debian.org/debian unstable/main i386 python3-webob all 1:1.8.7-1 [88.2 kB] Get: 116 http://deb.debian.org/debian unstable/main i386 python3-pyquery all 1.4.3-1 [23.1 kB] Get: 117 http://deb.debian.org/debian unstable/main i386 python3-pytest all 8.1.1-1 [245 kB] Get: 118 http://deb.debian.org/debian unstable/main i386 python3-urllib3 all 1.26.18-2 [116 kB] Get: 119 http://deb.debian.org/debian unstable/main i386 python3-requests all 2.31.0+dfsg-1 [68.6 kB] Get: 120 http://deb.debian.org/debian unstable/main i386 python3-retry all 0.9.2-2 [7020 B] Get: 121 http://deb.debian.org/debian unstable/main i386 python3-roundrobin all 0.0.4-3 [4364 B] Get: 122 http://deb.debian.org/debian unstable/main i386 python3-typing-extensions all 4.10.0-1 [66.2 kB] Get: 123 http://deb.debian.org/debian unstable/main i386 python3-zmq i386 24.0.1-5+b1 [362 kB] Fetched 48.1 MB in 2s (30.5 MB/s) debconf: delaying package configuration, since apt-utils is not installed Selecting previously unselected package fonts-lato. (Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading database ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 19645 files and directories currently installed.) Preparing to unpack .../fonts-lato_2.015-1_all.deb ... Unpacking fonts-lato (2.015-1) ... Selecting previously unselected package libpython3.11-minimal:i386. Preparing to unpack .../libpython3.11-minimal_3.11.8-3_i386.deb ... Unpacking libpython3.11-minimal:i386 (3.11.8-3) ... Selecting previously unselected package libexpat1:i386. Preparing to unpack .../libexpat1_2.6.2-1_i386.deb ... Unpacking libexpat1:i386 (2.6.2-1) ... Selecting previously unselected package python3.11-minimal. Preparing to unpack .../python3.11-minimal_3.11.8-3_i386.deb ... Unpacking python3.11-minimal (3.11.8-3) ... Setting up libpython3.11-minimal:i386 (3.11.8-3) ... Setting up libexpat1:i386 (2.6.2-1) ... Setting up python3.11-minimal (3.11.8-3) ... Selecting previously unselected package python3-minimal. (Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading database ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 19987 files and directories currently installed.) Preparing to unpack .../0-python3-minimal_3.11.8-1_i386.deb ... Unpacking python3-minimal (3.11.8-1) ... Selecting previously unselected package media-types. Preparing to unpack .../1-media-types_10.1.0_all.deb ... Unpacking media-types (10.1.0) ... Selecting previously unselected package netbase. Preparing to unpack .../2-netbase_6.4_all.deb ... Unpacking netbase (6.4) ... Selecting previously unselected package tzdata. Preparing to unpack .../3-tzdata_2024a-1_all.deb ... Unpacking tzdata (2024a-1) ... Selecting previously unselected package readline-common. Preparing to unpack .../4-readline-common_8.2-3.1_all.deb ... Unpacking readline-common (8.2-3.1) ... Selecting previously unselected package libreadline8t64:i386. Preparing to unpack .../5-libreadline8t64_8.2-3.1_i386.deb ... Adding 'diversion of /lib/i386-linux-gnu/libhistory.so.8 to /lib/i386-linux-gnu/libhistory.so.8.usr-is-merged by libreadline8t64' Adding 'diversion of /lib/i386-linux-gnu/libhistory.so.8.2 to /lib/i386-linux-gnu/libhistory.so.8.2.usr-is-merged by libreadline8t64' Adding 'diversion of /lib/i386-linux-gnu/libreadline.so.8 to /lib/i386-linux-gnu/libreadline.so.8.usr-is-merged by libreadline8t64' Adding 'diversion of /lib/i386-linux-gnu/libreadline.so.8.2 to /lib/i386-linux-gnu/libreadline.so.8.2.usr-is-merged by libreadline8t64' Unpacking libreadline8t64:i386 (8.2-3.1) ... Selecting previously unselected package libpython3.11-stdlib:i386. Preparing to unpack .../6-libpython3.11-stdlib_3.11.8-3_i386.deb ... Unpacking libpython3.11-stdlib:i386 (3.11.8-3) ... Selecting previously unselected package python3.11. Preparing to unpack .../7-python3.11_3.11.8-3_i386.deb ... Unpacking python3.11 (3.11.8-3) ... Selecting previously unselected package libpython3-stdlib:i386. Preparing to unpack .../8-libpython3-stdlib_3.11.8-1_i386.deb ... Unpacking libpython3-stdlib:i386 (3.11.8-1) ... Setting up python3-minimal (3.11.8-1) ... Selecting previously unselected package python3. (Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading database ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 20980 files and directories currently installed.) Preparing to unpack .../000-python3_3.11.8-1_i386.deb ... Unpacking python3 (3.11.8-1) ... Selecting previously unselected package libpython3.12-minimal:i386. Preparing to unpack .../001-libpython3.12-minimal_3.12.2-4_i386.deb ... Unpacking libpython3.12-minimal:i386 (3.12.2-4) ... Selecting previously unselected package python3.12-minimal. Preparing to unpack .../002-python3.12-minimal_3.12.2-4_i386.deb ... Unpacking python3.12-minimal (3.12.2-4) ... Selecting previously unselected package sensible-utils. Preparing to unpack .../003-sensible-utils_0.0.22_all.deb ... Unpacking sensible-utils (0.0.22) ... Selecting previously unselected package openssl. Preparing to unpack .../004-openssl_3.1.5-1.1_i386.deb ... Unpacking openssl (3.1.5-1.1) ... Selecting previously unselected package ca-certificates. Preparing to unpack .../005-ca-certificates_20240203_all.deb ... Unpacking ca-certificates (20240203) ... Selecting previously unselected package libmagic-mgc. Preparing to unpack .../006-libmagic-mgc_1%3a5.45-3_i386.deb ... Unpacking libmagic-mgc (1:5.45-3) ... Selecting previously unselected package libmagic1t64:i386. Preparing to unpack .../007-libmagic1t64_1%3a5.45-3_i386.deb ... Unpacking libmagic1t64:i386 (1:5.45-3) ... Selecting previously unselected package file. Preparing to unpack .../008-file_1%3a5.45-3_i386.deb ... Unpacking file (1:5.45-3) ... Selecting previously unselected package gettext-base. Preparing to unpack .../009-gettext-base_0.21-14+b1_i386.deb ... Unpacking gettext-base (0.21-14+b1) ... Selecting previously unselected package libuchardet0:i386. Preparing to unpack .../010-libuchardet0_0.0.8-1+b1_i386.deb ... Unpacking libuchardet0:i386 (0.0.8-1+b1) ... Selecting previously unselected package groff-base. Preparing to unpack .../011-groff-base_1.23.0-3+b1_i386.deb ... Unpacking groff-base (1.23.0-3+b1) ... Selecting previously unselected package bsdextrautils. Preparing to unpack .../012-bsdextrautils_2.39.3-10_i386.deb ... Unpacking bsdextrautils (2.39.3-10) ... Selecting previously unselected package libpipeline1:i386. Preparing to unpack .../013-libpipeline1_1.5.7-1+b2_i386.deb ... Unpacking libpipeline1:i386 (1.5.7-1+b2) ... Selecting previously unselected package man-db. Preparing to unpack .../014-man-db_2.12.0-3_i386.deb ... Unpacking man-db (2.12.0-3) ... Selecting previously unselected package m4. Preparing to unpack .../015-m4_1.4.19-4_i386.deb ... Unpacking m4 (1.4.19-4) ... Selecting previously unselected package autoconf. Preparing to unpack .../016-autoconf_2.71-3_all.deb ... Unpacking autoconf (2.71-3) ... Selecting previously unselected package autotools-dev. Preparing to unpack .../017-autotools-dev_20220109.1_all.deb ... Unpacking autotools-dev (20220109.1) ... Selecting previously unselected package automake. Preparing to unpack .../018-automake_1%3a1.16.5-1.3_all.deb ... Unpacking automake (1:1.16.5-1.3) ... Selecting previously unselected package autopoint. Preparing to unpack .../019-autopoint_0.21-14_all.deb ... Unpacking autopoint (0.21-14) ... Selecting previously unselected package libdebhelper-perl. Preparing to unpack .../020-libdebhelper-perl_13.14.1_all.deb ... Unpacking libdebhelper-perl (13.14.1) ... Selecting previously unselected package libtool. Preparing to unpack .../021-libtool_2.4.7-7_all.deb ... Unpacking libtool (2.4.7-7) ... Selecting previously unselected package dh-autoreconf. Preparing to unpack .../022-dh-autoreconf_20_all.deb ... Unpacking dh-autoreconf (20) ... Selecting previously unselected package libarchive-zip-perl. Preparing to unpack .../023-libarchive-zip-perl_1.68-1_all.deb ... Unpacking libarchive-zip-perl (1.68-1) ... Selecting previously unselected package libsub-override-perl. Preparing to unpack .../024-libsub-override-perl_0.10-1_all.deb ... Unpacking libsub-override-perl (0.10-1) ... Selecting previously unselected package libfile-stripnondeterminism-perl. Preparing to unpack .../025-libfile-stripnondeterminism-perl_1.13.1-1_all.deb ... Unpacking libfile-stripnondeterminism-perl (1.13.1-1) ... Selecting previously unselected package dh-strip-nondeterminism. Preparing to unpack .../026-dh-strip-nondeterminism_1.13.1-1_all.deb ... Unpacking dh-strip-nondeterminism (1.13.1-1) ... Selecting previously unselected package libelf1t64:i386. Preparing to unpack .../027-libelf1t64_0.191-1_i386.deb ... Unpacking libelf1t64:i386 (0.191-1) ... Selecting previously unselected package dwz. Preparing to unpack .../028-dwz_0.15-1+b1_i386.deb ... Unpacking dwz (0.15-1+b1) ... Selecting previously unselected package libicu72:i386. Preparing to unpack .../029-libicu72_72.1-4+b1_i386.deb ... Unpacking libicu72:i386 (72.1-4+b1) ... Selecting previously unselected package libxml2:i386. Preparing to unpack .../030-libxml2_2.9.14+dfsg-1.3+b2_i386.deb ... Unpacking libxml2:i386 (2.9.14+dfsg-1.3+b2) ... Selecting previously unselected package gettext. Preparing to unpack .../031-gettext_0.21-14+b1_i386.deb ... Unpacking gettext (0.21-14+b1) ... Selecting previously unselected package intltool-debian. Preparing to unpack .../032-intltool-debian_0.35.0+20060710.6_all.deb ... Unpacking intltool-debian (0.35.0+20060710.6) ... Selecting previously unselected package po-debconf. Preparing to unpack .../033-po-debconf_1.0.21+nmu1_all.deb ... Unpacking po-debconf (1.0.21+nmu1) ... Selecting previously unselected package debhelper. Preparing to unpack .../034-debhelper_13.14.1_all.deb ... Unpacking debhelper (13.14.1) ... Selecting previously unselected package python3-lib2to3. Preparing to unpack .../035-python3-lib2to3_3.12.2-3_all.deb ... Unpacking python3-lib2to3 (3.12.2-3) ... Selecting previously unselected package python3-distutils. Preparing to unpack .../036-python3-distutils_3.12.2-3_all.deb ... Unpacking python3-distutils (3.12.2-3) ... Selecting previously unselected package python3-pkg-resources. Preparing to unpack .../037-python3-pkg-resources_68.1.2-2_all.deb ... Unpacking python3-pkg-resources (68.1.2-2) ... Selecting previously unselected package python3-setuptools. Preparing to unpack .../038-python3-setuptools_68.1.2-2_all.deb ... Unpacking python3-setuptools (68.1.2-2) ... Selecting previously unselected package dh-python. Preparing to unpack .../039-dh-python_6.20240310_all.deb ... Unpacking dh-python (6.20240310) ... Selecting previously unselected package fonts-font-awesome. Preparing to unpack .../040-fonts-font-awesome_5.0.10+really4.7.0~dfsg-4.1_all.deb ... Unpacking fonts-font-awesome (5.0.10+really4.7.0~dfsg-4.1) ... Selecting previously unselected package libbsd0:i386. Preparing to unpack .../041-libbsd0_0.12.2-1_i386.deb ... Unpacking libbsd0:i386 (0.12.2-1) ... Selecting previously unselected package libc-ares2:i386. Preparing to unpack .../042-libc-ares2_1.27.0-1_i386.deb ... Unpacking libc-ares2:i386 (1.27.0-1) ... Selecting previously unselected package libcom-err2t64:i386. Preparing to unpack .../043-libcom-err2t64_1.47.0-2.3+b1_i386.deb ... Unpacking libcom-err2t64:i386 (1.47.0-2.3+b1) ... Selecting previously unselected package libev4t64:i386. Preparing to unpack .../044-libev4t64_1%3a4.33-2.1_i386.deb ... Unpacking libev4t64:i386 (1:4.33-2.1) ... Selecting previously unselected package libkrb5support0:i386. Preparing to unpack .../045-libkrb5support0_1.20.1-6_i386.deb ... Unpacking libkrb5support0:i386 (1.20.1-6) ... Selecting previously unselected package libk5crypto3:i386. Preparing to unpack .../046-libk5crypto3_1.20.1-6_i386.deb ... Unpacking libk5crypto3:i386 (1.20.1-6) ... Selecting previously unselected package libkeyutils1:i386. Preparing to unpack .../047-libkeyutils1_1.6.3-3_i386.deb ... Unpacking libkeyutils1:i386 (1.6.3-3) ... Selecting previously unselected package libkrb5-3:i386. Preparing to unpack .../048-libkrb5-3_1.20.1-6_i386.deb ... Unpacking libkrb5-3:i386 (1.20.1-6) ... Selecting previously unselected package libgssapi-krb5-2:i386. Preparing to unpack .../049-libgssapi-krb5-2_1.20.1-6_i386.deb ... Unpacking libgssapi-krb5-2:i386 (1.20.1-6) ... Selecting previously unselected package libjs-jquery. Preparing to unpack .../050-libjs-jquery_3.6.1+dfsg+~3.5.14-1_all.deb ... Unpacking libjs-jquery (3.6.1+dfsg+~3.5.14-1) ... Selecting previously unselected package libjs-underscore. Preparing to unpack .../051-libjs-underscore_1.13.4~dfsg+~1.11.4-3_all.deb ... Unpacking libjs-underscore (1.13.4~dfsg+~1.11.4-3) ... Selecting previously unselected package libjs-sphinxdoc. Preparing to unpack .../052-libjs-sphinxdoc_7.2.6-5_all.deb ... Unpacking libjs-sphinxdoc (7.2.6-5) ... Selecting previously unselected package libnorm1t64:i386. Preparing to unpack .../053-libnorm1t64_1.5.9+dfsg-3.1_i386.deb ... Unpacking libnorm1t64:i386 (1.5.9+dfsg-3.1) ... Selecting previously unselected package libpgm-5.3-0t64:i386. Preparing to unpack .../054-libpgm-5.3-0t64_5.3.128~dfsg-2.1_i386.deb ... Unpacking libpgm-5.3-0t64:i386 (5.3.128~dfsg-2.1) ... Selecting previously unselected package libpython3.12-stdlib:i386. Preparing to unpack .../055-libpython3.12-stdlib_3.12.2-4_i386.deb ... Unpacking libpython3.12-stdlib:i386 (3.12.2-4) ... Selecting previously unselected package libsodium23:i386. Preparing to unpack .../056-libsodium23_1.0.18-1_i386.deb ... Unpacking libsodium23:i386 (1.0.18-1) ... Selecting previously unselected package libxslt1.1:i386. Preparing to unpack .../057-libxslt1.1_1.1.35-1_i386.deb ... Unpacking libxslt1.1:i386 (1.1.35-1) ... Selecting previously unselected package libzmq5:i386. Preparing to unpack .../058-libzmq5_4.3.5-1+b2_i386.deb ... Unpacking libzmq5:i386 (4.3.5-1+b2) ... Selecting previously unselected package python3-packaging. Preparing to unpack .../059-python3-packaging_23.2-1_all.deb ... Unpacking python3-packaging (23.2-1) ... Selecting previously unselected package python3-pyproject-hooks. Preparing to unpack .../060-python3-pyproject-hooks_1.0.0-2_all.deb ... Unpacking python3-pyproject-hooks (1.0.0-2) ... Selecting previously unselected package python3-toml. Preparing to unpack .../061-python3-toml_0.10.2-1_all.deb ... Unpacking python3-toml (0.10.2-1) ... Selecting previously unselected package python3-wheel. Preparing to unpack .../062-python3-wheel_0.43.0-1_all.deb ... Unpacking python3-wheel (0.43.0-1) ... Selecting previously unselected package python3-build. Preparing to unpack .../063-python3-build_1.1.1-1_all.deb ... Unpacking python3-build (1.1.1-1) ... Selecting previously unselected package python3-installer. Preparing to unpack .../064-python3-installer_0.7.0+dfsg1-2_all.deb ... Unpacking python3-installer (0.7.0+dfsg1-2) ... Selecting previously unselected package pybuild-plugin-pyproject. Preparing to unpack .../065-pybuild-plugin-pyproject_6.20240310_all.deb ... Unpacking pybuild-plugin-pyproject (6.20240310) ... Selecting previously unselected package python3.12. Preparing to unpack .../066-python3.12_3.12.2-4_i386.deb ... Unpacking python3.12 (3.12.2-4) ... Selecting previously unselected package python3-all. Preparing to unpack .../067-python3-all_3.11.8-1_i386.deb ... Unpacking python3-all (3.11.8-1) ... Selecting previously unselected package python3-blinker. Preparing to unpack .../068-python3-blinker_1.7.0-1_all.deb ... Unpacking python3-blinker (1.7.0-1) ... Selecting previously unselected package python3-brotli. Preparing to unpack .../069-python3-brotli_1.1.0-2+b3_i386.deb ... Unpacking python3-brotli (1.1.0-2+b3) ... Selecting previously unselected package python3-certifi. Preparing to unpack .../070-python3-certifi_2023.11.17-1_all.deb ... Unpacking python3-certifi (2023.11.17-1) ... Selecting previously unselected package python3-cffi-backend:i386. Preparing to unpack .../071-python3-cffi-backend_1.16.0-2+b1_i386.deb ... Unpacking python3-cffi-backend:i386 (1.16.0-2+b1) ... Selecting previously unselected package python3-chardet. Preparing to unpack .../072-python3-chardet_5.2.0+dfsg-1_all.deb ... Unpacking python3-chardet (5.2.0+dfsg-1) ... Selecting previously unselected package python3-charset-normalizer. Preparing to unpack .../073-python3-charset-normalizer_3.3.2-1_all.deb ... Unpacking python3-charset-normalizer (3.3.2-1) ... Selecting previously unselected package python3-colorama. Preparing to unpack .../074-python3-colorama_0.4.6-4_all.deb ... Unpacking python3-colorama (0.4.6-4) ... Selecting previously unselected package python3-click. Preparing to unpack .../075-python3-click_8.1.7-1_all.deb ... Unpacking python3-click (8.1.7-1) ... Selecting previously unselected package python3-configargparse. Preparing to unpack .../076-python3-configargparse_1.7-1_all.deb ... Unpacking python3-configargparse (1.7-1) ... Selecting previously unselected package python3-cryptography. Preparing to unpack .../077-python3-cryptography_42.0.5-2_i386.deb ... Unpacking python3-cryptography (42.0.5-2) ... Selecting previously unselected package python3-cssselect. Preparing to unpack .../078-python3-cssselect_1.2.0-2_all.deb ... Unpacking python3-cssselect (1.2.0-2) ... Selecting previously unselected package python3-decorator. Preparing to unpack .../079-python3-decorator_5.1.1-5_all.deb ... Unpacking python3-decorator (5.1.1-5) ... Selecting previously unselected package python3-itsdangerous. Preparing to unpack .../080-python3-itsdangerous_2.1.2-4_all.deb ... Unpacking python3-itsdangerous (2.1.2-4) ... Selecting previously unselected package python3-markupsafe. Preparing to unpack .../081-python3-markupsafe_2.1.5-1_i386.deb ... Unpacking python3-markupsafe (2.1.5-1) ... Selecting previously unselected package python3-jinja2. Preparing to unpack .../082-python3-jinja2_3.1.3-1_all.deb ... Unpacking python3-jinja2 (3.1.3-1) ... Selecting previously unselected package python3-werkzeug. Preparing to unpack .../083-python3-werkzeug_3.0.1-3_all.deb ... Unpacking python3-werkzeug (3.0.1-3) ... Selecting previously unselected package python3-flask. Preparing to unpack .../084-python3-flask_3.0.2-1_all.deb ... Unpacking python3-flask (3.0.2-1) ... Selecting previously unselected package sphinx-rtd-theme-common. Preparing to unpack .../085-sphinx-rtd-theme-common_2.0.0+dfsg-1_all.deb ... Unpacking sphinx-rtd-theme-common (2.0.0+dfsg-1) ... Selecting previously unselected package python3-flask-cors. Preparing to unpack .../086-python3-flask-cors_4.0.0-1_all.deb ... Unpacking python3-flask-cors (4.0.0-1) ... Selecting previously unselected package python3-flask-login. Preparing to unpack .../087-python3-flask-login_0.6.3-1_all.deb ... Unpacking python3-flask-login (0.6.3-1) ... Selecting previously unselected package python3-greenlet. Preparing to unpack .../088-python3-greenlet_3.0.1-3_i386.deb ... Unpacking python3-greenlet (3.0.1-3) ... Selecting previously unselected package python3-zope.event. Preparing to unpack .../089-python3-zope.event_5.0-0.1_all.deb ... Unpacking python3-zope.event (5.0-0.1) ... Selecting previously unselected package python3-zope.interface. Preparing to unpack .../090-python3-zope.interface_6.1-1_i386.deb ... Unpacking python3-zope.interface (6.1-1) ... Selecting previously unselected package python3-gevent. Preparing to unpack .../091-python3-gevent_23.9.1-1+b1_i386.deb ... Unpacking python3-gevent (23.9.1-1+b1) ... Selecting previously unselected package python3-six. Preparing to unpack .../092-python3-six_1.16.0-6_all.deb ... Unpacking python3-six (1.16.0-6) ... Selecting previously unselected package python3-geventhttpclient. Preparing to unpack .../093-python3-geventhttpclient_2.0.11-2_i386.deb ... Unpacking python3-geventhttpclient (2.0.11-2) ... Selecting previously unselected package python3-idna. Preparing to unpack .../094-python3-idna_3.6-2_all.deb ... Unpacking python3-idna (3.6-2) ... Selecting previously unselected package python3-iniconfig. Preparing to unpack .../095-python3-iniconfig_1.1.1-2_all.deb ... Unpacking python3-iniconfig (1.1.1-2) ... Selecting previously unselected package python3-lxml:i386. Preparing to unpack .../096-python3-lxml_5.1.0-1_i386.deb ... Unpacking python3-lxml:i386 (5.1.0-1) ... Selecting previously unselected package python3-msgpack. Preparing to unpack .../097-python3-msgpack_1.0.3-3+b1_i386.deb ... Unpacking python3-msgpack (1.0.3-3+b1) ... Selecting previously unselected package python3-pluggy. Preparing to unpack .../098-python3-pluggy_1.4.0-1_all.deb ... Unpacking python3-pluggy (1.4.0-1) ... Selecting previously unselected package python3-psutil. Preparing to unpack .../099-python3-psutil_5.9.8-2_i386.deb ... Unpacking python3-psutil (5.9.8-2) ... Selecting previously unselected package python3-py. Preparing to unpack .../100-python3-py_1.11.0-2_all.deb ... Unpacking python3-py (1.11.0-2) ... Selecting previously unselected package python3-webob. Preparing to unpack .../101-python3-webob_1%3a1.8.7-1_all.deb ... Unpacking python3-webob (1:1.8.7-1) ... Selecting previously unselected package python3-pyquery. Preparing to unpack .../102-python3-pyquery_1.4.3-1_all.deb ... Unpacking python3-pyquery (1.4.3-1) ... Selecting previously unselected package python3-pytest. Preparing to unpack .../103-python3-pytest_8.1.1-1_all.deb ... Unpacking python3-pytest (8.1.1-1) ... Selecting previously unselected package python3-urllib3. Preparing to unpack .../104-python3-urllib3_1.26.18-2_all.deb ... Unpacking python3-urllib3 (1.26.18-2) ... Selecting previously unselected package python3-requests. Preparing to unpack .../105-python3-requests_2.31.0+dfsg-1_all.deb ... Unpacking python3-requests (2.31.0+dfsg-1) ... Selecting previously unselected package python3-retry. Preparing to unpack .../106-python3-retry_0.9.2-2_all.deb ... Unpacking python3-retry (0.9.2-2) ... Selecting previously unselected package python3-roundrobin. Preparing to unpack .../107-python3-roundrobin_0.0.4-3_all.deb ... Unpacking python3-roundrobin (0.0.4-3) ... Selecting previously unselected package python3-typing-extensions. Preparing to unpack .../108-python3-typing-extensions_4.10.0-1_all.deb ... Unpacking python3-typing-extensions (4.10.0-1) ... Selecting previously unselected package python3-zmq. Preparing to unpack .../109-python3-zmq_24.0.1-5+b1_i386.deb ... Unpacking python3-zmq (24.0.1-5+b1) ... Setting up media-types (10.1.0) ... Setting up libpipeline1:i386 (1.5.7-1+b2) ... Setting up libev4t64:i386 (1:4.33-2.1) ... Setting up libnorm1t64:i386 (1.5.9+dfsg-3.1) ... Setting up libkeyutils1:i386 (1.6.3-3) ... Setting up fonts-lato (2.015-1) ... Setting up libsodium23:i386 (1.0.18-1) ... Setting up libicu72:i386 (72.1-4+b1) ... Setting up bsdextrautils (2.39.3-10) ... Setting up libmagic-mgc (1:5.45-3) ... Setting up libarchive-zip-perl (1.68-1) ... Setting up libdebhelper-perl (13.14.1) ... Setting up libmagic1t64:i386 (1:5.45-3) ... Setting up libpython3.12-minimal:i386 (3.12.2-4) ... Setting up gettext-base (0.21-14+b1) ... Setting up m4 (1.4.19-4) ... Setting up libc-ares2:i386 (1.27.0-1) ... Setting up file (1:5.45-3) ... Setting up libelf1t64:i386 (0.191-1) ... Setting up libkrb5support0:i386 (1.20.1-6) ... Setting up tzdata (2024a-1) ... Current default time zone: 'Etc/UTC' Local time is now: Thu Mar 21 04:00:45 UTC 2024. Universal Time is now: Thu Mar 21 04:00:45 UTC 2024. Run 'dpkg-reconfigure tzdata' if you wish to change it. Setting up libpgm-5.3-0t64:i386 (5.3.128~dfsg-2.1) ... Setting up autotools-dev (20220109.1) ... Setting up libcom-err2t64:i386 (1.47.0-2.3+b1) ... Setting up autopoint (0.21-14) ... Setting up libk5crypto3:i386 (1.20.1-6) ... Setting up autoconf (2.71-3) ... Setting up dwz (0.15-1+b1) ... Setting up sensible-utils (0.0.22) ... Setting up libuchardet0:i386 (0.0.8-1+b1) ... Setting up libsub-override-perl (0.10-1) ... Setting up netbase (6.4) ... Setting up libkrb5-3:i386 (1.20.1-6) ... Setting up libjs-jquery (3.6.1+dfsg+~3.5.14-1) ... Setting up openssl (3.1.5-1.1) ... Setting up libbsd0:i386 (0.12.2-1) ... Setting up readline-common (8.2-3.1) ... Setting up libxml2:i386 (2.9.14+dfsg-1.3+b2) ... Setting up fonts-font-awesome (5.0.10+really4.7.0~dfsg-4.1) ... Setting up sphinx-rtd-theme-common (2.0.0+dfsg-1) ... Setting up libjs-underscore (1.13.4~dfsg+~1.11.4-3) ... Setting up automake (1:1.16.5-1.3) ... update-alternatives: using /usr/bin/automake-1.16 to provide /usr/bin/automake (automake) in auto mode Setting up libfile-stripnondeterminism-perl (1.13.1-1) ... Setting up python3.12-minimal (3.12.2-4) ... Setting up gettext (0.21-14+b1) ... Setting up libtool (2.4.7-7) ... Setting up intltool-debian (0.35.0+20060710.6) ... Setting up dh-autoreconf (20) ... Setting up ca-certificates (20240203) ... Updating certificates in /etc/ssl/certs... 146 added, 0 removed; done. Setting up libgssapi-krb5-2:i386 (1.20.1-6) ... Setting up libjs-sphinxdoc (7.2.6-5) ... Setting up libreadline8t64:i386 (8.2-3.1) ... Setting up dh-strip-nondeterminism (1.13.1-1) ... Setting up groff-base (1.23.0-3+b1) ... Setting up libxslt1.1:i386 (1.1.35-1) ... Setting up libzmq5:i386 (4.3.5-1+b2) ... Setting up libpython3.12-stdlib:i386 (3.12.2-4) ... Setting up po-debconf (1.0.21+nmu1) ... Setting up libpython3.11-stdlib:i386 (3.11.8-3) ... Setting up python3.12 (3.12.2-4) ... Setting up man-db (2.12.0-3) ... Not building database; man-db/auto-update is not 'true'. Setting up libpython3-stdlib:i386 (3.11.8-1) ... Setting up python3.11 (3.11.8-3) ... Setting up debhelper (13.14.1) ... Setting up python3 (3.11.8-1) ... Setting up python3-roundrobin (0.0.4-3) ... Setting up python3-markupsafe (2.1.5-1) ... Setting up python3-wheel (0.43.0-1) ... Setting up python3-psutil (5.9.8-2) ... Setting up python3-six (1.16.0-6) ... Setting up python3-decorator (5.1.1-5) ... Setting up python3-jinja2 (3.1.3-1) ... Setting up python3-packaging (23.2-1) ... Setting up python3-pyproject-hooks (1.0.0-2) ... Setting up python3-certifi (2023.11.17-1) ... Setting up python3-werkzeug (3.0.1-3) ... Setting up python3-brotli (1.1.0-2+b3) ... Setting up python3-greenlet (3.0.1-3) ... Setting up python3-idna (3.6-2) ... Setting up python3-typing-extensions (4.10.0-1) ... Setting up python3-toml (0.10.2-1) ... Setting up python3-installer (0.7.0+dfsg1-2) ... Setting up python3-urllib3 (1.26.18-2) ... Setting up python3-pluggy (1.4.0-1) ... Setting up python3-lxml:i386 (5.1.0-1) ... Setting up python3-msgpack (1.0.3-3+b1) ... Setting up python3-build (1.1.1-1) ... Setting up python3-cssselect (1.2.0-2) ... Setting up python3-lib2to3 (3.12.2-3) ... Setting up python3-cffi-backend:i386 (1.16.0-2+b1) ... Setting up python3-webob (1:1.8.7-1) ... Setting up python3-blinker (1.7.0-1) ... Setting up python3-pkg-resources (68.1.2-2) ... Setting up python3-distutils (3.12.2-3) ... python3.12: can't get files for byte-compilation Setting up python3-configargparse (1.7-1) ... Setting up python3-iniconfig (1.1.1-2) ... Setting up python3-setuptools (68.1.2-2) ... Setting up python3-py (1.11.0-2) ... Setting up python3-colorama (0.4.6-4) ... Setting up python3-zope.event (5.0-0.1) ... Setting up python3-zope.interface (6.1-1) ... Setting up python3-pyquery (1.4.3-1) ... Setting up python3-charset-normalizer (3.3.2-1) ... Setting up python3-pytest (8.1.1-1) ... Setting up python3-itsdangerous (2.1.2-4) ... Setting up python3-all (3.11.8-1) ... Setting up python3-gevent (23.9.1-1+b1) ... Setting up python3-click (8.1.7-1) ... Setting up python3-chardet (5.2.0+dfsg-1) ... Setting up python3-zmq (24.0.1-5+b1) ... Setting up python3-cryptography (42.0.5-2) ... Setting up python3-requests (2.31.0+dfsg-1) ... Setting up python3-retry (0.9.2-2) ... Setting up python3-geventhttpclient (2.0.11-2) ... Setting up dh-python (6.20240310) ... Setting up pybuild-plugin-pyproject (6.20240310) ... Setting up python3-flask (3.0.2-1) ... Setting up python3-flask-cors (4.0.0-1) ... Setting up python3-flask-login (0.6.3-1) ... Processing triggers for libc-bin (2.37-15.1) ... Processing triggers for ca-certificates (20240203) ... Updating certificates in /etc/ssl/certs... 0 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done. Reading package lists... Building dependency tree... Reading state information... Reading extended state information... Initializing package states... Writing extended state information... Building tag database... -> Finished parsing the build-deps Reading package lists... Building dependency tree... Reading state information... fakeroot is already the newest version (1.34-1). 0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded. I: Building the package I: user script /srv/workspace/pbuilder/54022/tmp/hooks/A99_set_merged_usr starting Not re-configuring usrmerge for unstable I: user script /srv/workspace/pbuilder/54022/tmp/hooks/A99_set_merged_usr finished hostname: Name or service not known I: Running cd /build/reproducible-path/locust-2.24.0/ && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-buildpackage -us -uc -b && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-genchanges -S > ../locust_2.24.0-1_source.changes dpkg-buildpackage: info: source package locust dpkg-buildpackage: info: source version 2.24.0-1 dpkg-buildpackage: info: source distribution unstable dpkg-buildpackage: info: source changed by Sandro Tosi dpkg-source --before-build . dpkg-buildpackage: info: host architecture i386 dpkg-source: info: using options from locust-2.24.0/debian/source/options: --extend-diff-ignore=^[^/]+.egg-info/ fakeroot debian/rules clean dh clean --with python3 --buildsystem=pybuild dh_auto_clean -O--buildsystem=pybuild dh_autoreconf_clean -O--buildsystem=pybuild debian/rules override_dh_clean make[1]: Entering directory '/build/reproducible-path/locust-2.24.0' rm -f locust/_version.py dh_clean make[1]: Leaving directory '/build/reproducible-path/locust-2.24.0' debian/rules build dh build --with python3 --buildsystem=pybuild dh_update_autotools_config -O--buildsystem=pybuild dh_autoreconf -O--buildsystem=pybuild dh_auto_configure -O--buildsystem=pybuild debian/rules execute_before_dh_auto_build make[1]: Entering directory '/build/reproducible-path/locust-2.24.0' echo "version = ''" > locust/_version.py make[1]: Leaving directory '/build/reproducible-path/locust-2.24.0' dh_auto_build -O--buildsystem=pybuild I: pybuild plugin_pyproject:129: Building wheel for python3.12 with "build" module I: pybuild base:305: python3.12 -m build --skip-dependency-check --no-isolation --wheel --outdir /build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.12_locust * Building wheel... running bdist_wheel running build running build_py creating build creating build/lib creating build/lib/locust copying locust/html.py -> build/lib/locust copying locust/shape.py -> build/lib/locust copying locust/stats.py -> build/lib/locust copying locust/event.py -> build/lib/locust copying locust/exception.py -> build/lib/locust copying locust/debug.py -> build/lib/locust copying locust/runners.py -> build/lib/locust copying locust/argument_parser.py -> build/lib/locust copying locust/log.py -> build/lib/locust copying locust/_version.py -> build/lib/locust copying locust/input_events.py -> build/lib/locust copying locust/__main__.py -> build/lib/locust copying locust/dispatch.py -> build/lib/locust copying locust/env.py -> build/lib/locust copying locust/__init__.py -> build/lib/locust copying locust/clients.py -> build/lib/locust copying locust/main.py -> build/lib/locust copying locust/web.py -> build/lib/locust creating build/lib/locust/test copying locust/test/test_main.py -> build/lib/locust/test copying locust/test/test_dispatch.py -> build/lib/locust/test copying locust/test/test_users.py -> build/lib/locust/test copying locust/test/test_load_locustfile.py -> build/lib/locust/test copying locust/test/test_fasthttp.py -> build/lib/locust/test copying locust/test/test_stats.py -> build/lib/locust/test copying locust/test/test_runners.py -> build/lib/locust/test copying locust/test/mock_locustfile.py -> build/lib/locust/test copying locust/test/fake_module2_for_env_test.py -> build/lib/locust/test copying locust/test/test_parser.py -> build/lib/locust/test copying locust/test/test_env.py -> build/lib/locust/test copying locust/test/test_sequential_taskset.py -> build/lib/locust/test copying locust/test/test_http.py -> build/lib/locust/test copying locust/test/test_util.py -> build/lib/locust/test copying locust/test/test_web.py -> build/lib/locust/test copying locust/test/fake_module1_for_env_test.py -> build/lib/locust/test copying locust/test/test_log.py -> build/lib/locust/test copying locust/test/test_tags.py -> build/lib/locust/test copying locust/test/mock_logging.py -> build/lib/locust/test copying locust/test/testcases.py -> build/lib/locust/test copying locust/test/test_taskratio.py -> build/lib/locust/test copying locust/test/test_interruptable_task.py -> build/lib/locust/test copying locust/test/test_wait_time.py -> build/lib/locust/test copying locust/test/test_zmqrpc.py -> build/lib/locust/test copying locust/test/test_locust_class.py -> build/lib/locust/test copying locust/test/util.py -> build/lib/locust/test copying locust/test/__init__.py -> build/lib/locust/test copying locust/test/test_debugging.py -> build/lib/locust/test copying locust/test/test_old_wait_api.py -> build/lib/locust/test creating build/lib/locust/user copying locust/user/users.py -> build/lib/locust/user copying locust/user/inspectuser.py -> build/lib/locust/user copying locust/user/wait_time.py -> build/lib/locust/user copying locust/user/__init__.py -> build/lib/locust/user copying locust/user/sequential_taskset.py -> build/lib/locust/user copying locust/user/task.py -> build/lib/locust/user creating build/lib/locust/contrib copying locust/contrib/fasthttp.py -> build/lib/locust/contrib copying locust/contrib/__init__.py -> build/lib/locust/contrib creating build/lib/locust/util copying locust/util/deprecation.py -> build/lib/locust/util copying locust/util/timespan.py -> build/lib/locust/util copying locust/util/rounding.py -> build/lib/locust/util copying locust/util/load_locustfile.py -> build/lib/locust/util copying locust/util/__init__.py -> build/lib/locust/util copying locust/util/exception_handler.py -> build/lib/locust/util copying locust/util/cache.py -> build/lib/locust/util creating build/lib/locust/rpc copying locust/rpc/__init__.py -> build/lib/locust/rpc copying locust/rpc/protocol.py -> build/lib/locust/rpc copying locust/rpc/zmqrpc.py -> build/lib/locust/rpc copying locust/py.typed -> build/lib/locust creating build/lib/locust/templates copying locust/templates/stats_data.html -> build/lib/locust/templates copying locust/templates/index.html -> build/lib/locust/templates copying locust/templates/report.html -> build/lib/locust/templates creating build/lib/locust/static copying locust/static/echarts.common.min.js -> build/lib/locust/static copying locust/static/locust.js -> build/lib/locust/static copying locust/static/jquery-1.11.3.min.js -> build/lib/locust/static copying locust/static/tasks.js -> build/lib/locust/static copying locust/static/chart.js -> build/lib/locust/static copying locust/static/jquery.jqote2.min.js -> build/lib/locust/static copying locust/static/vintage.js -> build/lib/locust/static copying locust/static/jquery.tools.min.js -> build/lib/locust/static creating build/lib/locust/static/css copying locust/static/css/application.css.map -> build/lib/locust/static/css copying locust/static/css/application.css -> build/lib/locust/static/css copying locust/static/css/tables.css -> build/lib/locust/static/css copying locust/static/css/tables.css.map -> build/lib/locust/static/css creating build/lib/locust/static/sass copying locust/static/sass/application.sass -> build/lib/locust/static/sass copying locust/static/sass/tables.sass -> build/lib/locust/static/sass copying locust/static/sass/_base.sass -> build/lib/locust/static/sass copying locust/static/sass/_mixins.sass -> build/lib/locust/static/sass creating build/lib/locust/static/img copying locust/static/img/logo.png -> build/lib/locust/static/img copying locust/static/img/favicon.ico -> build/lib/locust/static/img copying locust/static/img/ui-screenshot-workers.png -> build/lib/locust/static/img copying locust/static/img/ui-screenshot-stats.png -> build/lib/locust/static/img copying locust/static/img/ui-screenshot-start-test.png -> build/lib/locust/static/img copying locust/static/img/ui-screenshot-charts.png -> build/lib/locust/static/img creating build/lib/locust/webui creating build/lib/locust/webui/dist copying locust/webui/dist/index.html -> build/lib/locust/webui/dist copying locust/webui/dist/auth.html -> build/lib/locust/webui/dist copying locust/webui/dist/report.html -> build/lib/locust/webui/dist creating build/lib/locust/webui/dist/assets copying locust/webui/dist/assets/logo.png -> build/lib/locust/webui/dist/assets copying locust/webui/dist/assets/favicon.ico -> build/lib/locust/webui/dist/assets copying locust/webui/dist/assets/index-0d6d578a.js -> build/lib/locust/webui/dist/assets installing to build/bdist.linux-i686/wheel running install running install_lib creating build/bdist.linux-i686 creating build/bdist.linux-i686/wheel creating build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_main.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_dispatch.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_users.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_load_locustfile.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_fasthttp.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_stats.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_runners.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/mock_locustfile.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/fake_module2_for_env_test.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_parser.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_env.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_sequential_taskset.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_http.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_util.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_web.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/fake_module1_for_env_test.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_log.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_tags.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/mock_logging.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/testcases.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_taskratio.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_interruptable_task.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_wait_time.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_zmqrpc.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_locust_class.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/util.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/__init__.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_debugging.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_old_wait_api.py -> build/bdist.linux-i686/wheel/locust/test creating build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/stats_data.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/index.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/report.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/py.typed -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/html.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/shape.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/users.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/inspectuser.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/wait_time.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/__init__.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/sequential_taskset.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/task.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/stats.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/event.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/exception.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/debug.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/runners.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/argument_parser.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/contrib/fasthttp.py -> build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/contrib/__init__.py -> build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/log.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/_version.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/webui creating build/bdist.linux-i686/wheel/locust/webui/dist creating build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/logo.png -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/favicon.ico -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/index-0d6d578a.js -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/index.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/webui/dist/auth.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/webui/dist/report.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/input_events.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/__main__.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/dispatch.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/env.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/__init__.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/clients.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/deprecation.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/timespan.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/rounding.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/load_locustfile.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/__init__.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/exception_handler.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/cache.py -> build/bdist.linux-i686/wheel/locust/util creating build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/__init__.py -> build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/protocol.py -> build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/zmqrpc.py -> build/bdist.linux-i686/wheel/locust/rpc creating build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/application.css.map -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/application.css -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/tables.css -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/tables.css.map -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/echarts.common.min.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/locust.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery-1.11.3.min.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/tasks.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/chart.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery.jqote2.min.js -> build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/application.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/tables.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/_base.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/_mixins.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/vintage.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery.tools.min.js -> build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/logo.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/favicon.ico -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-workers.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-stats.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-start-test.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-charts.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/main.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/web.py -> build/bdist.linux-i686/wheel/locust running install_egg_info running egg_info creating locust.egg-info writing locust.egg-info/PKG-INFO writing dependency_links to locust.egg-info/dependency_links.txt writing entry points to locust.egg-info/entry_points.txt writing requirements to locust.egg-info/requires.txt writing top-level names to locust.egg-info/top_level.txt writing manifest file 'locust.egg-info/SOURCES.txt' reading manifest file 'locust.egg-info/SOURCES.txt' reading manifest template 'MANIFEST.in' adding license file 'LICENSE' writing manifest file 'locust.egg-info/SOURCES.txt' Copying locust.egg-info to build/bdist.linux-i686/wheel/locust-0.0.0.egg-info running install_scripts creating build/bdist.linux-i686/wheel/locust-0.0.0.dist-info/WHEEL creating '/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.12_locust/.tmp-uvut2tsx/locust-0.0.0-py3-none-any.whl' and adding 'build/bdist.linux-i686/wheel' to it adding 'locust/__init__.py' adding 'locust/__main__.py' adding 'locust/_version.py' adding 'locust/argument_parser.py' adding 'locust/clients.py' adding 'locust/debug.py' adding 'locust/dispatch.py' adding 'locust/env.py' adding 'locust/event.py' adding 'locust/exception.py' adding 'locust/html.py' adding 'locust/input_events.py' adding 'locust/log.py' adding 'locust/main.py' adding 'locust/py.typed' adding 'locust/runners.py' adding 'locust/shape.py' adding 'locust/stats.py' adding 'locust/web.py' adding 'locust/contrib/__init__.py' adding 'locust/contrib/fasthttp.py' adding 'locust/rpc/__init__.py' adding 'locust/rpc/protocol.py' adding 'locust/rpc/zmqrpc.py' adding 'locust/static/chart.js' adding 'locust/static/echarts.common.min.js' adding 'locust/static/jquery-1.11.3.min.js' adding 'locust/static/jquery.jqote2.min.js' adding 'locust/static/jquery.tools.min.js' adding 'locust/static/locust.js' adding 'locust/static/tasks.js' adding 'locust/static/vintage.js' adding 'locust/static/css/application.css' adding 'locust/static/css/application.css.map' adding 'locust/static/css/tables.css' adding 'locust/static/css/tables.css.map' adding 'locust/static/img/favicon.ico' adding 'locust/static/img/logo.png' adding 'locust/static/img/ui-screenshot-charts.png' adding 'locust/static/img/ui-screenshot-start-test.png' adding 'locust/static/img/ui-screenshot-stats.png' adding 'locust/static/img/ui-screenshot-workers.png' adding 'locust/static/sass/_base.sass' adding 'locust/static/sass/_mixins.sass' adding 'locust/static/sass/application.sass' adding 'locust/static/sass/tables.sass' adding 'locust/templates/index.html' adding 'locust/templates/report.html' adding 'locust/templates/stats_data.html' adding 'locust/test/__init__.py' adding 'locust/test/fake_module1_for_env_test.py' adding 'locust/test/fake_module2_for_env_test.py' adding 'locust/test/mock_locustfile.py' adding 'locust/test/mock_logging.py' adding 'locust/test/test_debugging.py' adding 'locust/test/test_dispatch.py' adding 'locust/test/test_env.py' adding 'locust/test/test_fasthttp.py' adding 'locust/test/test_http.py' adding 'locust/test/test_interruptable_task.py' adding 'locust/test/test_load_locustfile.py' adding 'locust/test/test_locust_class.py' adding 'locust/test/test_log.py' adding 'locust/test/test_main.py' adding 'locust/test/test_old_wait_api.py' adding 'locust/test/test_parser.py' adding 'locust/test/test_runners.py' adding 'locust/test/test_sequential_taskset.py' adding 'locust/test/test_stats.py' adding 'locust/test/test_tags.py' adding 'locust/test/test_taskratio.py' adding 'locust/test/test_users.py' adding 'locust/test/test_util.py' adding 'locust/test/test_wait_time.py' adding 'locust/test/test_web.py' adding 'locust/test/test_zmqrpc.py' adding 'locust/test/testcases.py' adding 'locust/test/util.py' adding 'locust/user/__init__.py' adding 'locust/user/inspectuser.py' adding 'locust/user/sequential_taskset.py' adding 'locust/user/task.py' adding 'locust/user/users.py' adding 'locust/user/wait_time.py' adding 'locust/util/__init__.py' adding 'locust/util/cache.py' adding 'locust/util/deprecation.py' adding 'locust/util/exception_handler.py' adding 'locust/util/load_locustfile.py' adding 'locust/util/rounding.py' adding 'locust/util/timespan.py' adding 'locust/webui/dist/auth.html' adding 'locust/webui/dist/index.html' adding 'locust/webui/dist/report.html' adding 'locust/webui/dist/assets/favicon.ico' adding 'locust/webui/dist/assets/index-0d6d578a.js' adding 'locust/webui/dist/assets/logo.png' adding 'locust-0.0.0.dist-info/LICENSE' adding 'locust-0.0.0.dist-info/METADATA' adding 'locust-0.0.0.dist-info/WHEEL' adding 'locust-0.0.0.dist-info/entry_points.txt' adding 'locust-0.0.0.dist-info/top_level.txt' adding 'locust-0.0.0.dist-info/RECORD' removing build/bdist.linux-i686/wheel Successfully built locust-0.0.0-py3-none-any.whl I: pybuild plugin_pyproject:144: Unpacking wheel built for python3.12 with "installer" module I: pybuild plugin_pyproject:129: Building wheel for python3.11 with "build" module I: pybuild base:305: python3.11 -m build --skip-dependency-check --no-isolation --wheel --outdir /build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.11_locust * Building wheel... running bdist_wheel running build running build_py installing to build/bdist.linux-i686/wheel running install running install_lib creating build/bdist.linux-i686/wheel creating build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_main.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_dispatch.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_users.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_load_locustfile.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_fasthttp.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_stats.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_runners.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/mock_locustfile.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/fake_module2_for_env_test.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_parser.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_env.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_sequential_taskset.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_http.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_util.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_web.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/fake_module1_for_env_test.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_log.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_tags.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/mock_logging.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/testcases.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_taskratio.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_interruptable_task.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_wait_time.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_zmqrpc.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_locust_class.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/util.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/__init__.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_debugging.py -> build/bdist.linux-i686/wheel/locust/test copying build/lib/locust/test/test_old_wait_api.py -> build/bdist.linux-i686/wheel/locust/test creating build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/stats_data.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/index.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/templates/report.html -> build/bdist.linux-i686/wheel/locust/templates copying build/lib/locust/py.typed -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/html.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/shape.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/users.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/inspectuser.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/wait_time.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/__init__.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/sequential_taskset.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/user/task.py -> build/bdist.linux-i686/wheel/locust/user copying build/lib/locust/stats.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/event.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/exception.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/debug.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/runners.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/argument_parser.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/contrib/fasthttp.py -> build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/contrib/__init__.py -> build/bdist.linux-i686/wheel/locust/contrib copying build/lib/locust/log.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/_version.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/webui creating build/bdist.linux-i686/wheel/locust/webui/dist creating build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/logo.png -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/favicon.ico -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/assets/index-0d6d578a.js -> build/bdist.linux-i686/wheel/locust/webui/dist/assets copying build/lib/locust/webui/dist/index.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/webui/dist/auth.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/webui/dist/report.html -> build/bdist.linux-i686/wheel/locust/webui/dist copying build/lib/locust/input_events.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/__main__.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/dispatch.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/env.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/__init__.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/clients.py -> build/bdist.linux-i686/wheel/locust creating build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/deprecation.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/timespan.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/rounding.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/load_locustfile.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/__init__.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/exception_handler.py -> build/bdist.linux-i686/wheel/locust/util copying build/lib/locust/util/cache.py -> build/bdist.linux-i686/wheel/locust/util creating build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/__init__.py -> build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/protocol.py -> build/bdist.linux-i686/wheel/locust/rpc copying build/lib/locust/rpc/zmqrpc.py -> build/bdist.linux-i686/wheel/locust/rpc creating build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/application.css.map -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/application.css -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/tables.css -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/css/tables.css.map -> build/bdist.linux-i686/wheel/locust/static/css copying build/lib/locust/static/echarts.common.min.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/locust.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery-1.11.3.min.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/tasks.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/chart.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery.jqote2.min.js -> build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/application.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/tables.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/_base.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/sass/_mixins.sass -> build/bdist.linux-i686/wheel/locust/static/sass copying build/lib/locust/static/vintage.js -> build/bdist.linux-i686/wheel/locust/static copying build/lib/locust/static/jquery.tools.min.js -> build/bdist.linux-i686/wheel/locust/static creating build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/logo.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/favicon.ico -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-workers.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-stats.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-start-test.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/static/img/ui-screenshot-charts.png -> build/bdist.linux-i686/wheel/locust/static/img copying build/lib/locust/main.py -> build/bdist.linux-i686/wheel/locust copying build/lib/locust/web.py -> build/bdist.linux-i686/wheel/locust running install_egg_info running egg_info writing locust.egg-info/PKG-INFO writing dependency_links to locust.egg-info/dependency_links.txt writing entry points to locust.egg-info/entry_points.txt writing requirements to locust.egg-info/requires.txt writing top-level names to locust.egg-info/top_level.txt reading manifest file 'locust.egg-info/SOURCES.txt' reading manifest template 'MANIFEST.in' adding license file 'LICENSE' writing manifest file 'locust.egg-info/SOURCES.txt' Copying locust.egg-info to build/bdist.linux-i686/wheel/locust-0.0.0.egg-info running install_scripts creating build/bdist.linux-i686/wheel/locust-0.0.0.dist-info/WHEEL creating '/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.11_locust/.tmp-d_dg_ehb/locust-0.0.0-py3-none-any.whl' and adding 'build/bdist.linux-i686/wheel' to it adding 'locust/__init__.py' adding 'locust/__main__.py' adding 'locust/_version.py' adding 'locust/argument_parser.py' adding 'locust/clients.py' adding 'locust/debug.py' adding 'locust/dispatch.py' adding 'locust/env.py' adding 'locust/event.py' adding 'locust/exception.py' adding 'locust/html.py' adding 'locust/input_events.py' adding 'locust/log.py' adding 'locust/main.py' adding 'locust/py.typed' adding 'locust/runners.py' adding 'locust/shape.py' adding 'locust/stats.py' adding 'locust/web.py' adding 'locust/contrib/__init__.py' adding 'locust/contrib/fasthttp.py' adding 'locust/rpc/__init__.py' adding 'locust/rpc/protocol.py' adding 'locust/rpc/zmqrpc.py' adding 'locust/static/chart.js' adding 'locust/static/echarts.common.min.js' adding 'locust/static/jquery-1.11.3.min.js' adding 'locust/static/jquery.jqote2.min.js' adding 'locust/static/jquery.tools.min.js' adding 'locust/static/locust.js' adding 'locust/static/tasks.js' adding 'locust/static/vintage.js' adding 'locust/static/css/application.css' adding 'locust/static/css/application.css.map' adding 'locust/static/css/tables.css' adding 'locust/static/css/tables.css.map' adding 'locust/static/img/favicon.ico' adding 'locust/static/img/logo.png' adding 'locust/static/img/ui-screenshot-charts.png' adding 'locust/static/img/ui-screenshot-start-test.png' adding 'locust/static/img/ui-screenshot-stats.png' adding 'locust/static/img/ui-screenshot-workers.png' adding 'locust/static/sass/_base.sass' adding 'locust/static/sass/_mixins.sass' adding 'locust/static/sass/application.sass' adding 'locust/static/sass/tables.sass' adding 'locust/templates/index.html' adding 'locust/templates/report.html' adding 'locust/templates/stats_data.html' adding 'locust/test/__init__.py' adding 'locust/test/fake_module1_for_env_test.py' adding 'locust/test/fake_module2_for_env_test.py' adding 'locust/test/mock_locustfile.py' adding 'locust/test/mock_logging.py' adding 'locust/test/test_debugging.py' adding 'locust/test/test_dispatch.py' adding 'locust/test/test_env.py' adding 'locust/test/test_fasthttp.py' adding 'locust/test/test_http.py' adding 'locust/test/test_interruptable_task.py' adding 'locust/test/test_load_locustfile.py' adding 'locust/test/test_locust_class.py' adding 'locust/test/test_log.py' adding 'locust/test/test_main.py' adding 'locust/test/test_old_wait_api.py' adding 'locust/test/test_parser.py' adding 'locust/test/test_runners.py' adding 'locust/test/test_sequential_taskset.py' adding 'locust/test/test_stats.py' adding 'locust/test/test_tags.py' adding 'locust/test/test_taskratio.py' adding 'locust/test/test_users.py' adding 'locust/test/test_util.py' adding 'locust/test/test_wait_time.py' adding 'locust/test/test_web.py' adding 'locust/test/test_zmqrpc.py' adding 'locust/test/testcases.py' adding 'locust/test/util.py' adding 'locust/user/__init__.py' adding 'locust/user/inspectuser.py' adding 'locust/user/sequential_taskset.py' adding 'locust/user/task.py' adding 'locust/user/users.py' adding 'locust/user/wait_time.py' adding 'locust/util/__init__.py' adding 'locust/util/cache.py' adding 'locust/util/deprecation.py' adding 'locust/util/exception_handler.py' adding 'locust/util/load_locustfile.py' adding 'locust/util/rounding.py' adding 'locust/util/timespan.py' adding 'locust/webui/dist/auth.html' adding 'locust/webui/dist/index.html' adding 'locust/webui/dist/report.html' adding 'locust/webui/dist/assets/favicon.ico' adding 'locust/webui/dist/assets/index-0d6d578a.js' adding 'locust/webui/dist/assets/logo.png' adding 'locust-0.0.0.dist-info/LICENSE' adding 'locust-0.0.0.dist-info/METADATA' adding 'locust-0.0.0.dist-info/WHEEL' adding 'locust-0.0.0.dist-info/entry_points.txt' adding 'locust-0.0.0.dist-info/top_level.txt' adding 'locust-0.0.0.dist-info/RECORD' removing build/bdist.linux-i686/wheel Successfully built locust-0.0.0-py3-none-any.whl I: pybuild plugin_pyproject:144: Unpacking wheel built for python3.11 with "installer" module debian/rules override_dh_auto_test make[1]: Entering directory '/build/reproducible-path/locust-2.24.0' # examples/test_data_management.py - attempted network access during pytest collection phase # TestMasterWorkerRunners times out after a long time http_proxy= https_proxy= PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path:/build/reproducible-path/locust-2.24.0/debian PYBUILD_SYSTEM=custom PYBUILD_TEST_ARGS="PYTHONPATH={build_dir} {interpreter} -m pytest -v --ignore=examples/test_data_management.py -k 'not TestMasterWorkerRunners'" dh_auto_test I: pybuild base:305: PYTHONPATH=/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.12_locust/build python3.12 -m pytest -v --ignore=examples/test_data_management.py -k 'not TestMasterWorkerRunners' ============================= test session starts ============================== platform linux -- Python 3.12.2, pytest-8.1.1, pluggy-1.4.0 -- /usr/bin/python3.12 cachedir: .pytest_cache rootdir: /build/reproducible-path/locust-2.24.0 configfile: pyproject.toml collecting ... collected 564 items / 15 deselected / 549 selected locust/test/test_debugging.py::TestDebugging::test_run_single_user_pass_host_to_user_classes PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_0_5 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_1 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_2 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_2_4 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_3 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_4 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_9 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_4_workers_with_spawn_rate_of_1 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_users_are_distributed_evenly_across_hosts PASSED [ 1%] locust/test/test_dispatch.py::TestWaitBetweenDispatch::test_wait_between_dispatch PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_0_5 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_1 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_2 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_2_4 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_3 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_4 PASSED [ 3%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_9 PASSED [ 3%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_4_workers_with_spawn_rate_of_1 PASSED [ 3%] locust/test/test_dispatch.py::TestRampUpThenDownThenUp::test_ramp_up_then_down_then_up SKIPPED [ 3%] locust/test/test_dispatch.py::TestDispatchUsersToWorkersHavingTheSameUsersAsTheTarget::test_dispatch_users_to_3_workers PASSED [ 3%] locust/test/test_dispatch.py::TestDistributionIsRespectedDuringDispatch::test_dispatch_75_users_to_4_workers_with_spawn_rate_of_5 PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_distribute_users PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_ramp_down_from_100_000_to_0_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_ramp_up_from_0_to_100_000_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate PASSED [ 4%] locust/test/test_dispatch.py::TestSmallConsecutiveRamping::test_consecutive_ramp_up_and_ramp_down PASSED [ 4%] locust/test/test_dispatch.py::TestRampingMiscellaneous::test_spawn_rate_greater_than_target_user_count PASSED [ 4%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_last_worker PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_between_two_ramp_ups PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_during_ramp_down PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_during_ramp_up PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_between_two_ramp_ups PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_down PASSED [ 6%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_up PASSED [ 6%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_up_with_fixed_user PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_between_two_ramp_ups PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_during_ramp_down PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_during_ramp_up PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_between_two_ramp_ups PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_down PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_up PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_up_with_fixed_user PASSED [ 7%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_2_weigted_user_with_1_fixed_user PASSED [ 7%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_only_fixed_users PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_partially_ramp_down_and_rump_up_to_target PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_ramp_down_and_ramp_up_again PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_ramp_down_and_ramp_up_again_single_fixed_class PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_various_count_weigted_and_fixed_users PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_add_worker_during_ramp_up_custom_classes PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_down_custom_user_classes_respect_weighting PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_different_users_each_dispatch_multiple_worker PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_different_users_for_each_dispatch PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_first_half_user1_second_half_user2 PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_first_one_user_then_all_classes PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_one_user_class_multiple_worker PASSED [ 10%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_only_one_kind_of_user PASSED [ 10%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_remove_worker_during_ramp_up_custom_classes PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_all_user_classes_with_zero_weight_raises_exception PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_assign_equal_weights PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_dispatcher_class_attribute PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_shape_class_attribute PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_update_user_class PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_count PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_with_same_name_is_error PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_with_zero_weight_are_removed PASSED [ 11%] locust/test/test_fasthttp.py::TestFastHttpSession::test_204 PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_404 PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_default_fail PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_default_success PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_fail_successful_request PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_multiple_failure_and_success PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_pass_failed_request PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_pass_failed_request_with_other_exception_within_block PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_connection_error PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_cookie PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_custom_ssl_context_fail_with_bad_context PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_custom_ssl_context_passed_correct_to_client_pool PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_delete PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_error_message_with_name_replacement PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_get PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_head PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_json_payload PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_options PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_patch PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_post_redirect PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_slow_redirect PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_streaming_response PASSED [ 15%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_connection_error PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_content_length PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length_streaming PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_put PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_query_variables PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_allow_redirects_override PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_class_context PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_basic_auth PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_delete PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_get PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_get_absolute_url PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_head PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_pool_concurrency PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_pool_per_user_instance PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_post PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_put PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_request_headers PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_complex_content_type PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_get_request PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_is_abstract PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_log_request_name_argument PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_max_redirect_setting PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_network_timeout_setting PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_redirect_url_original_path_as_name PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_shared_client_pool PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_slow_redirect PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_allow_404 PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_connection_error_fail PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_connection_error_success PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_fail PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_manual_fail PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_manual_success PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_missing_with_block PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_interrupt_taskset_with_catch_response PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_missing_catch_response_true PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_rest_fail PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_rest_success PASSED [ 23%] locust/test/test_fasthttp.py::TestFastHttpSsl::test_ssl_request_insecure PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_default_fail PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_default_success PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_fail_successful_request PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_fail_successful_request_with_non_string_error_message PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_missing_with_block PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_multiple_failure_and_success PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_pass_failed_request PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_pass_failed_request_with_other_exception_within_block PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_response_error PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_timeout PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_catch_response_with_name_replacement PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_connection_error PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_context_in_success PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_cookie PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_delete PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_error_message PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_error_message_with_name_replacement PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_event_measure FAILED [ 26%] locust/test/test_http.py::TestHttpSession::test_get PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_get_with_params PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_head PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_missing_catch_response_true PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_options PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_post_redirect PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_response_parameter PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_slow_redirect PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_streaming_response PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_user_context PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_wrong_url PASSED [ 28%] locust/test/test_interruptable_task.py::TestInterruptableTask::test_interruptable_task PASSED [ 28%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_command_line_arguments_override_config_file PASSED [ 28%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_create_environment PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_is_user_class PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_called_locust_dot_py PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_from_absolute_path PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_from_relative_path PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_with_a_dot_in_filename PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_can_be_set_in_config_file PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_from_url FAILED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_return_docstring_and_user_classes PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_specify_config_file PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_abstract_shape_class PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_multiple_shape_classes PASSED [ 31%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_not_imported_shape_class PASSED [ 31%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_shape_class PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_start PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_start_interrupt PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_interrupt PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_interrupt_reschedule PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_when_locust_stops PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_parent_attribute PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_schedule_task PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_schedule_task_bound_method PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_sub_taskset PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_sub_taskset_tasks_decorator PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_on_taskset PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_ratio PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_with_or_without_argument PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_ratio PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_missing_from_user_gives_user_friendly_exception PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_missing_gives_user_friendly_exception PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_on_abstract_locust PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_on_locust PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_taskset_inheritance PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_taskset_on_abstract_locust PASSED [ 35%] locust/test/test_locust_class.py::TestTaskSet::test_user_is_read_only PASSED [ 35%] locust/test/test_locust_class.py::TestTaskSet::test_wait_function PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_deprecated_locust_class PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_locust_forced_stop PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_locust_graceful_stop PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_on_start PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_on_stop PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_start PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_wait PASSED [ 36%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_basic_auth PASSED [ 36%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_delete PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_get PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_get_absolute_url PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_head PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_post PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_put PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_request_headers PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_get_request PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_log_request_name_argument PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_redirect_url_original_path_as_name PASSED [ 38%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response PASSED [ 38%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_allow_404 PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_connection_error_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_connection_error_success PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_manual_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_manual_success PASSED [ 40%] locust/test/test_locust_class.py::TestCatchResponse::test_interrupt_taskset_with_catch_response PASSED [ 40%] locust/test/test_log.py::TestGreenletExceptionLogger::test_greenlet_exception_logger PASSED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_log_to_file FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_logging_output FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_skip_logging FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_user_broken_on_start FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_multiple_locustfiles_with_shape FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_load_shape FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_run_time FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_wo_run_time FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_command_line_user_selection FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments_in_file FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_exit_code FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options_with_shape FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_shape_class_names FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_userclass_names FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_locustfiles_directory_is_empty FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_no_tasks_match_tags FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_providing_both_run_time_and_a_shape_class FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_graceful_exit_when_keyboard_interrupt FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_headless_spawn_options_wo_run_time FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_help_arg FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_html_report_option FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_input FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_percentile_parameter FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_stop_timeout_string FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_no_error_when_same_userclass_in_two_files FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_percentile_parameter FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_percentiles_to_statistics FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_autostart_with_multiple_locustfiles FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles_with_shape FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_with_userclass_picker FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_log_disabled_parameters FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_with_use_common_options FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_spawing_with_fixed_multiple_locustfiles FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_spawning_with_fixed FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_web_options FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_in_directory FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_with_shape FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_events FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_report_timeout_expired FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_tags FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_with_locustfile_distribution_not_plain_filename FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_expect_workers FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_json_schema FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution_with_workers_started_first FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_processes FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_autodetect FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_ctrl_c FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_error_doesnt_blow_up_completely FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_separate_worker FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_workers_quit_unexpected FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_worker_indexes FAILED [ 51%] locust/test/test_main.py::DistributedIntegrationTests::test_workers_shut_down_if_master_is_gone FAILED [ 51%] locust/test/test_parser.py::TestParser::test_default PASSED [ 51%] locust/test/test_parser.py::TestParser::test_parse_options_from_conf_file PASSED [ 51%] locust/test/test_parser.py::TestParser::test_parse_options_from_toml_file PASSED [ 51%] locust/test/test_parser.py::TestParser::test_reset_stats PASSED [ 51%] locust/test/test_parser.py::TestParser::test_skip_log_setup PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_csv_full_history_requires_csv PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument_help_message PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument_included_in_web_ui PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_empty_directory_error PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_invalid_directory_error PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_multiple_files PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_directory PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_directory_ignores_invalid_filenames PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_nested_directory PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_parse_options PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_parse_options_from_env PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_unknown_command_line_arg PASSED [ 54%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_for_invalid_file_extension PASSED [ 54%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_directory_doesnt_exist PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_invalid_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_multiple_values_for_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_ignores_invalid_files_in_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_with_is_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_with_multiple_locustfiles PASSED [ 55%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_false_if_file_and_directory_share_the_same_name PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_multiple_locustfiles PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_single_locustfile PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_single_locustfile_without_file_extension PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_true_if_directory PASSED [ 56%] locust/test/test_runners.py::TestLocustRunner::test_attributes_populated_when_calling_start PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_can_call_stop_endpoint_if_currently_swarming PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_change_user_count_during_spawning PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_cpu_warning PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_custom_dispatcher_class PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_custom_message PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_duplicate_message_handler_registration PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_host_class_attribute_from_web PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_kill_locusts PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_no_reset_stats PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_reset_stats PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_runner_quit_can_run_on_stop_for_multiple_users_concurrently PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_runner_reference_on_environment PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_start_event PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event_quit PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event_stop_and_quit PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_users_count PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_stop_users_with_spawn_rate PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_stopping_event PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_swarm_endpoint_is_non_blocking PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_target_user_count_is_set_before_ramp_up PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_undefined_custom_message PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_user_classes_count PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_user_count_starts_from_specified_amount_when_creating_new_test_after_previous_step_has_been_stopped PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_users_can_call_runner_quit_without_deadlocking PASSED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_attributes_populated_when_calling_start FAILED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_custom_message_receive PASSED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_custom_message_send PASSED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_down FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_interval FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_up FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_exception_in_task PASSED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_exception_is_caught PASSED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_last_worker_missing_stops_test FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_last_worker_quitting_stops_test FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_current_response_times PASSED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_discard_first_client_ready FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_marks_downed_workers_as_missing FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_reset_connection FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_master_total_stats PASSED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_master_total_stats_with_none_response_times PASSED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_rebalance_locust_users_on_worker_connect FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_reset_connection_after_RPCError FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_sends_spawn_data_to_ready_running_spawning_workers PASSED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_correct_worker_indexes FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_fewer_locusts_than_workers FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_uneven_locusts FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_zero_locusts PASSED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_start_event FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_stop_event FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_stop_event_quit FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_undefined_custom_message_receive PASSED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_unknown_host_sends_message_to_master FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_wait_for_workers_report_after_ramp_up PASSED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_worker_connect FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_connect_with_special_versions FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_missing_after_heartbeat_dead_interval FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_sends_bad_message_to_master FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_sends_unrecognized_message_to_master FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_stats_report_median PASSED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_stats_report_with_none_response_times PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_change_user_count_during_spawning PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_computed_properties PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_custom_message_receive PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_custom_message_send PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_reset_rpc_connection_to_master PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_spawn_message_with_older_timestamp_is_rejected PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_start_event PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_stop_event PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_undefined_custom_message_receive PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_worker_connect_failure PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_worker_connect_success PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_heartbeat_messages_sent_to_master PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_messages_sent_to_master PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_stop_timeout PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_without_stop_timeout PASSED [ 70%] locust/test/test_runners.py::TestMessageSerializing::test_message_serialize PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_gracefully_handle_exceptions_in_listener PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_kill_locusts_with_stop_timeout PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_during_on_start PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_exit_during_wait PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_interrupt PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_interrupt_no_reschedule PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_ramp_down PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_users_can_call_runner_quit_with_stop_timeout PASSED [ 72%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_multiple_iterations PASSED [ 72%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_inheritance PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_list PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_methods PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_methods_and_list PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation_last_request_timestamp PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation_min_response_time PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_aggregation_with_decimal_rounding PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_aggregation_with_rounding PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_avg PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_avg_only_none PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_current_fail_per_sec PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_current_rps PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_custom_percentile_list PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_error_grouping PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_error_grouping_errors_with_memory_addresses PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_median PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_median_out_of_min_max_bounds PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_num_reqs_fails PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile_rounded_down PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile_rounded_up PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_reset PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_reset_min_response_time PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_rps_less_than_one_second PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_serialize_through_message PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_total_content_length PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_total_rps PASSED [ 77%] locust/test/test_stats.py::TestStatsPrinting::test_print_error_report PASSED [ 78%] locust/test/test_stats.py::TestStatsPrinting::test_print_percentile_stats PASSED [ 78%] locust/test/test_stats.py::TestStatsPrinting::test_print_stats PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_on_master_from_aggregated_stats PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_writer PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_writer_full_history PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_requests_csv_quote_escaping PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_stats_history FAILED [ 79%] locust/test/test_stats.py::TestCsvStats::test_user_count_in_csv_history_stats PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_write_csv_files PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_write_csv_files_full_history PASSED [ 79%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_diff_response_times_dicts PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_get_current_response_time_percentile PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_get_current_response_time_percentile_outside_cache_window PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_latest_total_response_times_pruned PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_response_times_cached PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_response_times_not_cached_if_not_enabled PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_all_failures PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_half_failures PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_no_failures PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_connection_error PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_content_length PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint_rename_request PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint_request_name PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length_streaming PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_put PASSED [ 83%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_query_variables PASSED [ 83%] locust/test/test_stats.py::TestInspectUser::test_get_task_ratio_relative PASSED [ 83%] locust/test/test_stats.py::TestInspectUser::test_get_task_ratio_total PASSED [ 83%] locust/test/test_tags.py::TestTags::test_env_exclude_tags PASSED [ 83%] locust/test/test_tags.py::TestTags::test_env_include_tags PASSED [ 83%] locust/test/test_tags.py::TestTags::test_exclude_tags_under_user PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tags PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tags_with_weights PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tasksets PASSED [ 84%] locust/test/test_tags.py::TestTags::test_include_tags_under_user PASSED [ 84%] locust/test/test_tags.py::TestTags::test_including_and_excluding PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tags PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tags_with_weights PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tasksets PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagged_tasks_shared_across_tasksets PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagging PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagging_taskset PASSED [ 86%] locust/test/test_tags.py::TestTags::test_tagging_without_args_fails PASSED [ 86%] locust/test/test_taskratio.py::TestTaskRatio::test_task_ratio_command PASSED [ 86%] locust/test/test_taskratio.py::TestTaskRatio::test_task_ratio_command_with_locust_weight PASSED [ 86%] locust/test/test_users.py::TestUserClass::test_fullname_class_scoped PASSED [ 86%] locust/test/test_users.py::TestUserClass::test_fullname_function_scoped PASSED [ 87%] locust/test/test_users.py::TestUserClass::test_fullname_module_scoped PASSED [ 87%] locust/test/test_users.py::TestHttpUserWithWebserver::test_pool_manager_per_user_instance PASSED [ 87%] locust/test/test_users.py::TestHttpUserWithWebserver::test_shared_pool_manager PASSED [ 87%] locust/test/test_util.py::TestParseTimespan::test_parse_timespan PASSED [ 87%] locust/test/test_util.py::TestParseTimespan::test_parse_timespan_invalid_values PASSED [ 87%] locust/test/test_util.py::TestRounding::test_rounding_down PASSED [ 88%] locust/test/test_util.py::TestRounding::test_rounding_up PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_between PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_constant PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_constant_throughput PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_default_wait_time PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_argument_dropdown PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_shape_deactivate_num_users_and_spawn_rate PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_shape_with_use_common_options_keep_num_users_and_spawn_rate PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_exceptions PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_exceptions_csv PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_failure_stats_csv PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_multiple_user_classes PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_multiple_user_classes_different_hosts PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_user_class PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_html_stats_report PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_index PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_index_with_spawn_options PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_logs PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_download PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_exceptions PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_host PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_host2 PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_report_page PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_report_page_empty_stats PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_csv PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_full_history_csv_not_present PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_with_errors PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_reset_stats PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_cache PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_no_data PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_rounding PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_swarm_custom_argument PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_defaults_to_all_available_userclasses_when_userclass_picker_is_active_and_no_userclass_in_payload PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_error_when_userclass_picker_is_active_but_no_available_userclasses PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_host_value_not_specified PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_host_value_specified PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_multiple_userclasses_specified PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time_empty_input PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time_invalid_input PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_defaults_to_none_when_userclass_picker_is_active PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_is_updated_when_userclass_picker_is_active PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_updates_parsed_options_when_multiple_userclasses_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_updates_parsed_options_when_single_userclass_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_userclass_shapeclass_ignored_when_userclass_picker_is_inactive PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_userclass_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_uses_pre_selected_user_classes_when_empty_payload_and_test_is_already_running_with_class_picker PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_template_args PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_update_user_endpoint PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_web_ui_no_runner PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_web_ui_reference_on_environment PASSED [ 97%] locust/test/test_web.py::TestWebUIAuth::test_index_with_web_login_enabled_no_user PASSED [ 97%] locust/test/test_web.py::TestWebUIAuth::test_index_with_web_login_enabled_valid_user PASSED [ 98%] locust/test/test_web.py::TestWebUIWithTLS::test_index_with_https PASSED [ 98%] locust/test/test_web.py::TestWebUIFullHistory::test_request_stats_full_history_csv PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_html_stats_report PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_index_with_modern_ui PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_web_ui_no_runner PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_recv PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_retry PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_send PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_constructor PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_rpc_error PASSED [100%] =================================== FAILURES =================================== ______________________ TestHttpSession.test_event_measure ______________________ self = def test_event_measure(self): kwargs = {} def on_request(**kw): kwargs.update(**kw) self.environment.events.request.add_listener(on_request) with self.environment.events.request.measure("GET", "/test") as request_meta: time.sleep(0.001) > self.assertTrue(1 <= kwargs["response_time"] <= 1.5, kwargs["response_time"]) E AssertionError: False is not true : 3.887898987159133 locust/test/test_http.py:293: AssertionError _________________ TestLoadLocustfile.test_locustfile_from_url __________________ self = def _new_conn(self): """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ extra_kw = {} if self.source_address: extra_kw["source_address"] = self.source_address if self.socket_options: extra_kw["socket_options"] = self.socket_options try: > conn = connection.create_connection( (self._dns_host, self.port), self.timeout, **extra_kw ) /usr/lib/python3/dist-packages/urllib3/connection.py:174: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/util/connection.py:73: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): /usr/lib/python3/dist-packages/gevent/_socketcommon.py:225: in getaddrinfo addrlist = get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags) /usr/lib/python3/dist-packages/gevent/resolver/thread.py:63: in getaddrinfo return self.pool.apply(_socket.getaddrinfo, args, kwargs) /usr/lib/python3/dist-packages/gevent/pool.py:161: in apply return self.spawn(func, *args, **kwds).get() src/gevent/event.py:329: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:359: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:347: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:327: in gevent._gevent_cevent.AsyncResult._raise_exception ??? /usr/lib/python3/dist-packages/gevent/_compat.py:49: in reraise raise value.with_traceback(tb) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ # Copyright (c) 2012 Denis Bilenko. See LICENSE for details. from __future__ import absolute_import from __future__ import division from __future__ import print_function import os import sys from greenlet import greenlet as RawGreenlet from gevent import monkey from gevent._compat import integer_types from gevent.event import AsyncResult from gevent.exceptions import InvalidThreadUseError from gevent.greenlet import Greenlet from gevent._hub_local import get_hub_if_exists from gevent.hub import _get_hub_noargs as get_hub from gevent.hub import getcurrent from gevent.hub import sleep from gevent.lock import Semaphore from gevent.pool import GroupMappingMixin from gevent.util import clear_stack_frames from gevent._threading import Queue from gevent._threading import EmptyTimeout from gevent._threading import start_new_thread from gevent._threading import get_thread_ident __all__ = [ 'ThreadPool', 'ThreadResult', ] def _format_hub(hub): if hub is None: return '' return '<%s at 0x%x thread_ident=0x%x>' % ( hub.__class__.__name__, id(hub), hub.thread_ident ) def _get_thread_profile(_sys=sys): if 'threading' in _sys.modules: return _sys.modules['threading']._profile_hook def _get_thread_trace(_sys=sys): if 'threading' in _sys.modules: return _sys.modules['threading']._trace_hook class _WorkerGreenlet(RawGreenlet): # Exists to produce a more useful repr for worker pool # threads/greenlets, and manage the communication of the worker # thread with the threadpool. # Inform the gevent.util.GreenletTree that this should be # considered the root (for printing purposes) greenlet_tree_is_root = True _thread_ident = 0 _exc_info = sys.exc_info _get_hub_if_exists = staticmethod(get_hub_if_exists) # We capture the hub each time through the loop in case its created # so we can destroy it after a fork. _hub_of_worker = None # The hub of the threadpool we're working for. Just for info. _hub = None # A cookie passed to task_queue.get() _task_queue_cookie = None # If not -1, how long to block waiting for a task before we # exit. _idle_task_timeout = -1 def __init__(self, threadpool): # Construct in the main thread (owner of the threadpool) # The parent greenlet and thread identifier will be set once the # new thread begins running. RawGreenlet.__init__(self) self._hub = threadpool.hub # Avoid doing any imports in the background thread if it's not # necessary (monkey.get_original imports if not patched). # Background imports can hang Python 2 (gevent's thread resolver runs in the BG, # and resolving may have to import the idna module, which needs an import lock, so # resolving at module scope) if monkey.is_module_patched('sys'): stderr = monkey.get_original('sys', 'stderr') else: stderr = sys.stderr self._stderr = stderr # We can capture the task_queue; even though it can change if the threadpool # is re-innitted, we won't be running in that case self._task_queue = threadpool.task_queue # type:gevent._threading.Queue self._task_queue_cookie = self._task_queue.allocate_cookie() self._unregister_worker = threadpool._unregister_worker self._idle_task_timeout = threadpool._idle_task_timeout threadpool._register_worker(self) try: start_new_thread(self._begin, ()) except: self._unregister_worker(self) raise def _begin(self, _get_c=getcurrent, _get_ti=get_thread_ident): # Pass arguments to avoid accessing globals during module shutdown. # we're in the new thread (but its root greenlet). Establish invariants and get going # by making this the current greenlet. self.parent = _get_c() # pylint:disable=attribute-defined-outside-init self._thread_ident = _get_ti() # ignore the parent attribute. (We can't set parent to None.) self.parent.greenlet_tree_is_ignored = True try: self.switch() # goto run() except: # pylint:disable=bare-except # run() will attempt to print any exceptions, but that might # not work during shutdown. sys.excepthook and such may be gone, # so things might not get printed at all except for a cryptic # message. This is especially true on Python 2 (doesn't seem to be # an issue on Python 3). pass def __fixup_hub_before_block(self): hub = self._get_hub_if_exists() # Don't create one; only set if a worker function did it if hub is not None: hub.name = 'ThreadPool Worker Hub' # While we block, don't let the monitoring thread, if any, # report us as blocked. Indeed, so long as we never # try to switch greenlets, don't report us as blocked--- # the threadpool is *meant* to run blocking tasks if hub is not None and hub.periodic_monitoring_thread is not None: hub.periodic_monitoring_thread.ignore_current_greenlet_blocking() self._hub_of_worker = hub @staticmethod def __print_tb(tb, stderr): # Extracted from traceback to avoid accessing any module # globals (these sometimes happen during interpreter shutdown; # see test__subprocess_interrupted) while tb is not None: f = tb.tb_frame lineno = tb.tb_lineno co = f.f_code filename = co.co_filename name = co.co_name print(' File "%s", line %d, in %s' % (filename, lineno, name), file=stderr) tb = tb.tb_next def _before_run_task(self, func, args, kwargs, thread_result, _sys=sys, _get_thread_profile=_get_thread_profile, _get_thread_trace=_get_thread_trace): # pylint:disable=unused-argument _sys.setprofile(_get_thread_profile()) _sys.settrace(_get_thread_trace()) def _after_run_task(self, func, args, kwargs, thread_result, _sys=sys): # pylint:disable=unused-argument _sys.setprofile(None) _sys.settrace(None) def __run_task(self, func, args, kwargs, thread_result): self._before_run_task(func, args, kwargs, thread_result) try: > thread_result.set(func(*args, **kwargs)) E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib/python3/dist-packages/gevent/threadpool.py:173: gaierror During handling of the above exception, another exception occurred: self = method = 'GET', url = '/locustio/locust/master/examples/basic.py', body = None headers = {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None response_kw = {'decode_content': False, 'preload_content': False} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/locustio/locust/master/examples/basic.py', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( self, method, url, body=None, headers=None, retries=None, redirect=True, assert_same_host=True, timeout=_Default, pool_timeout=None, release_conn=None, chunked=False, body_pos=None, **response_kw ): """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method provided by :class:`.RequestMethods`, such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. Pass ``None`` to retry until you receive a response. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``response_kw.get('preload_content', True)``. :param chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. :param \\**response_kw: Additional parameters are passed to :meth:`urllib3.response.HTTPResponse.from_httplib` """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = response_kw.get("preload_content", True) # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = six.ensure_str(_encode_target(url)) else: url = six.ensure_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() headers.update(self.proxy_headers) # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout is_new_proxy_conn = self.proxy is not None and not getattr( conn, "sock", None ) if is_new_proxy_conn and http_tunnel_required: self._prepare_proxy(conn) # Make the request on the httplib connection object. > httplib_response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, ) /usr/lib/python3/dist-packages/urllib3/connectionpool.py:716: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/connectionpool.py:405: in _make_request self._validate_conn(conn) /usr/lib/python3/dist-packages/urllib3/connectionpool.py:1059: in _validate_conn conn.connect() /usr/lib/python3/dist-packages/urllib3/connection.py:363: in connect self.sock = conn = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self): """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ extra_kw = {} if self.source_address: extra_kw["source_address"] = self.source_address if self.socket_options: extra_kw["socket_options"] = self.socket_options try: conn = connection.create_connection( (self._dns_host, self.port), self.timeout, **extra_kw ) except SocketTimeout: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout), ) except SocketError as e: > raise NewConnectionError( self, "Failed to establish a new connection: %s" % e ) E urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno -3] Temporary failure in name resolution /usr/lib/python3/dist-packages/urllib3/connection.py:186: NewConnectionError During handling of the above exception, another exception occurred: self = request = , stream = False timeout = Timeout(connect=None, read=None, total=None), verify = True cert = None, proxies = OrderedDict({'no': 'localhost'}) def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection(request.url, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3/dist-packages/requests/adapters.py:486: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/connectionpool.py:800: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/locustio/locust/master/examples/basic.py' response = None error = NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution') _pool = _stacktrace = def increment( self, method=None, url=None, response=None, error=None, _pool=None, _stacktrace=None, ): """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.HTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise six.reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise six.reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or not self._is_method_retryable(method): raise six.reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" redirect_location = response.get_redirect_location() status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): > raise MaxRetryError(_pool, url, error or ResponseError(cause)) E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) /usr/lib/python3/dist-packages/urllib3/util/retry.py:592: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py' def download_locustfile_from_url(url: str) -> str: try: > response = requests.get(url) locust/argument_parser.py:193: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /usr/lib/python3/dist-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /usr/lib/python3/dist-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /usr/lib/python3/dist-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=None, read=None, total=None), verify = True cert = None, proxies = OrderedDict({'no': 'localhost'}) def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection(request.url, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) /usr/lib/python3/dist-packages/requests/adapters.py:519: ConnectionError During handling of the above exception, another exception occurred: self = def test_locustfile_from_url(self): > locustfiles = parse_locustfile_option( args=[ "-f", "https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py", ] ) locust/test/test_load_locustfile.py:216: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/argument_parser.py:370: in parse_locustfile_option download_locustfile_from_url(f) if is_url(f.strip()) else f.strip() for f in options.locustfile.split(",") _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py' def download_locustfile_from_url(url: str) -> str: try: response = requests.get(url) # Check if response is valid python code ast.parse(response.text) except requests.exceptions.RequestException as e: sys.stderr.write(f"Failed to get locustfile from: {url}. Exception: {e}") > sys.exit(1) E SystemExit: 1 locust/argument_parser.py:198: SystemExit ----------------------------- Captured stderr call ----------------------------- Failed to get locustfile from: https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py. Exception: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) _____________________ TestLoggingOptions.test_log_to_file ______________________ self = def test_log_to_file(self): with temporary_file( textwrap.dedent( """ import logging from locust import User, task, constant class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") logging.info("custom log message") """ ) ) as file_path: with temporary_file("", suffix=".log") as log_file_path: try: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", "--logfile", log_file_path, ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:158: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp3k678oeq_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________________ TestLoggingOptions.test_logging_output ____________________ self = def test_logging_output(self): with temporary_file( textwrap.dedent( """ import logging from locust import User, task, constant custom_logger = logging.getLogger("custom_logger") class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") logging.info("custom log message") custom_logger.info("test") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpoxpxaoz3_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________________ TestLoggingOptions.test_skip_logging _____________________ self = def test_skip_logging(self): with temporary_file( textwrap.dedent( """ from locust import User, task, constant class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", "--skip-log-setup", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:117: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmphg0tdq0a_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ TestLoggingOptions.test_user_broken_on_start _________________ self = def test_user_broken_on_start(self): with temporary_file( textwrap.dedent( """ from locust import HttpUser, task class TestUser(HttpUser): host = "invalidhost" def on_start(self): self.client.get("/") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-t", "1", "--headless", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:223: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp_j21z4k8_locustfile.py', '-t', '1', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_autostart_multiple_locustfiles_with_shape ___ self = def test_autostart_multiple_locustfiles_with_shape(self): port = get_free_tcp_port() content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( [ "locust", "-f", f"{mocked1.file_path},{mocked2}", "--legacy-ui", "--web-port", str(port), "--autostart", "--autoquit", "3", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:794: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993761_9687426_47244.py,/tmp/tmpwqvc46od_locustfile.py', '--legacy-ui', '--web-port', '50845', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________ StandaloneIntegrationTests.test_autostart_w_load_shape ____________ self = def test_autostart_w_load_shape(self): port = get_free_tcp_port() with mock_locustfile( content=MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) ) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--legacy-ui", "--web-port", str(port), "--autostart", "--autoquit", "3", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:727: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993762_1370413_91618.py', '--legacy-ui', '--web-port', '57147', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________ StandaloneIntegrationTests.test_autostart_w_run_time _____________ self = @unittest.skipIf(sys.platform == "darwin", reason="This is too messy on macOS") def test_autostart_w_run_time(self): port = get_free_tcp_port() with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--web-port", str(port), "-t", "3", "--autostart", "--autoquit", "1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:635: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993762_3031328_54829.py', '--web-port', '60805', '-t', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________ StandaloneIntegrationTests.test_autostart_wo_run_time _____________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_autostart_wo_run_time(self): port = get_free_tcp_port() with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--web-port", str(port), "--autostart", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:600: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993762_463063_34269.py', '--web-port', '40795', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________ StandaloneIntegrationTests.test_command_line_user_selection __________ self = def test_command_line_user_selection(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): print("User1 is running") class User2(User): wait_time = constant(1) @task def t(self): print("User2 is running") class User3(User): wait_time = constant(1) @task def t(self): print("User3 is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "2s", "-u", "5", "-r", "10", "User2", "User3", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] self.assertNotIn("User1 is running", output) > self.assertIn("User2 is running", output) E AssertionError: 'User2 is running' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1080: AssertionError _______________ StandaloneIntegrationTests.test_custom_arguments _______________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_arguments(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.init_command_line_parser.add_listener def _(parser, **kw): parser.add_argument("--custom-string-arg") class TestUser(User): wait_time = constant(10) @task def my_task(self): print(self.environment.parsed_options.custom_string_arg) """ ) ) as file_path: # print(subprocess.check_output(["cat", file_path])) > proc = subprocess.Popen( ["locust", "-f", file_path, "--custom-string-arg", "command_line_value", "--web-port", str(port)], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:104: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp8ep6i60e_locustfile.py', '--custom-string-arg', 'command_line_value', '--web-port', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________ StandaloneIntegrationTests.test_custom_arguments_in_file ___________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_arguments_in_file(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.init_command_line_parser.add_listener def _(parser, **kw): parser.add_argument("--custom-string-arg") class TestUser(User): wait_time = constant(10) @task def my_task(self): print(self.environment.parsed_options.custom_string_arg) """ ) ) as file_path: try: with open("locust.conf", "w") as conf_file: conf_file.write("custom-string-arg config_file_value") > proc = subprocess.Popen( ["locust", "-f", file_path, "--autostart"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:147: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp1qzfkxsz_locustfile.py', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ StandaloneIntegrationTests.test_custom_exit_code _______________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_exit_code(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.quitting.add_listener def _(environment, **kw): environment.process_exit_code = 42 @events.quit.add_listener def _(exit_code, **kw): print(f"Exit code in quit event {exit_code}") class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:182: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp_bvhee1b_locustfile.py'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 80, errread = 81 errwrite = 82, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_default_headless_spawn_options ________ self = def test_default_headless_spawn_options(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--run-time", "1s", "--headless", "--loglevel", "DEBUG", "--exit-code-on-error", "0", # just to test --stop-timeout argument parsing, doesnt actually validate its function: "--stop-timeout", "1s", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:371: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993763_2208927_87057.py', '--host', 'https://test.com/', '--run-time', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_default_headless_spawn_options_with_shape ___ self = @unittest.skipIf(sys.version_info < (3, 9), reason="dies in 3.8 on GH and I cant be bothered to investigate it") def test_default_headless_spawn_options_with_shape(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993763_376689_53049.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_error_when_duplicate_shape_class_names ____ self = def test_error_when_duplicate_shape_class_names(self): MOCK_LOCUSTFILE_CONTENT_C = MOCK_LOCUSTFILE_CONTENT_A + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) MOCK_LOCUSTFILE_CONTENT_D = MOCK_LOCUSTFILE_CONTENT_B + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_D) as file2: > proc = subprocess.Popen(["locust", "-f", f"{file1},{file2}"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1209: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpbc3e2v9m_locustfile.py,/tmp/tmpnsoop43k_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_error_when_duplicate_userclass_names _____ self = def test_error_when_duplicate_userclass_names(self): MOCK_LOCUSTFILE_CONTENT_C = textwrap.dedent( """ from locust import User, task, constant, events class TestUser1(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file2: > proc = subprocess.Popen(["locust", "-f", f"{file1},{file2}"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1157: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpwjxsuoy2_locustfile.py,/tmp/tmp2zf0hrtj_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_error_when_locustfiles_directory_is_empty ___ self = def test_error_when_locustfiles_directory_is_empty(self): with TemporaryDirectory() as temp_dir: > proc = subprocess.Popen(["locust", "-f", temp_dir], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1298: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpdu9q2zcy'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 80, errread = 81 errwrite = 82, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_error_when_no_tasks_match_tags ________ self = def test_error_when_no_tasks_match_tags(self): content = """ from locust import HttpUser, TaskSet, task, constant, LoadTestShape, tag class MyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = constant(1) @tag("tag1") @task def task1(self): print("task1") """ with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "-t", "1", "--tags", "tag2", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1317: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993763_9958344_12726.py', '--headless', '-t', '1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_error_when_providing_both_run_time_and_a_shape_class _ self = def test_error_when_providing_both_run_time_and_a_shape_class(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "-f", mocked.file_path, "--run-time=1s", "--headless", "--exit-code-on-error", "0", ] ) locust/test/test_main.py:1226: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993764_173823_32329.py', '--run-time=1s', '--headless', '--exit-code-on-error', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_graceful_exit_when_keyboard_interrupt _____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_graceful_exit_when_keyboard_interrupt(self): with temporary_file( content=textwrap.dedent( """ from locust import User, events, task, constant, LoadTestShape @events.test_stop.add_listener def on_test_stop(environment, **kwargs) -> None: print("Test Stopped") class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked, "--headless", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1363: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpbkkl7jvz_locustfile.py', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______ StandaloneIntegrationTests.test_headless_spawn_options_wo_run_time ______ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_headless_spawn_options_wo_run_time(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:421: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993764_5634673_38442.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________________ StandaloneIntegrationTests.test_help_arg ___________________ self = def test_help_arg(self): > output = subprocess.check_output( ["locust", "--help"], stderr=subprocess.STDOUT, timeout=5, text=True, ).strip() locust/test/test_main.py:72: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , args = ['locust', '--help'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______________ StandaloneIntegrationTests.test_html_report_option ______________ self = def test_html_report_option(self): with mock_locustfile() as mocked: with temporary_file("", suffix=".html") as html_report_file_path: try: > output = subprocess.check_output( [ "locust", "-f", mocked.file_path, "--legacy-ui", "--host", "https://test.com/", "--run-time", "2s", "--headless", "--exit-code-on-error", "0", "--html", html_report_file_path, ], stderr=subprocess.STDOUT, timeout=10, text=True, ).strip() locust/test/test_main.py:1088: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993764_8853061_16495.py', '--legacy-ui', '--host', 'https://test.com/', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________________ StandaloneIntegrationTests.test_input _____________________ self = @unittest.skipIf(os.name == "nt", reason="termios doesnt exist on windows, and thus we cannot import pty") def test_input(self): import pty LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, TaskSet, task, between class UserSubclass(User): wait_time = between(0.2, 0.8) @task def t(self): print("Test task is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: stdin_m, stdin_s = pty.openpty() stdin = os.fdopen(stdin_m, "wb", 0) proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "7s", "-u", "0", "--loglevel", "INFO", ] ), stderr=STDOUT, stdin=stdin_s, stdout=PIPE, shell=True, text=True, ) gevent.sleep(1) stdin.write(b"w") gevent.sleep(1) stdin.write(b"W") gevent.sleep(1) stdin.write(b"s") gevent.sleep(1) stdin.write(b"S") gevent.sleep(1) # This should not do anything since we are already at zero users stdin.write(b"S") gevent.sleep(1) output = proc.communicate()[0] stdin.close() > self.assertIn("Ramping to 1 users at a rate of 100.00 per second", output) E AssertionError: 'Ramping to 1 users at a rate of 100.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:922: AssertionError _________ StandaloneIntegrationTests.test_invalid_percentile_parameter _________ self = def test_invalid_percentile_parameter(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_CHART PERCENTILES_TO_CHART[0] = 1.2 class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path, "--autostart"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:287: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpu_p4hkp8_locustfile.py', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________ StandaloneIntegrationTests.test_invalid_stop_timeout_string __________ self = def test_invalid_stop_timeout_string(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--stop-timeout", "asdf1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:400: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993771_389403_74777.py', '--host', 'https://test.com/', '--stop-timeout', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_no_error_when_same_userclass_in_two_files ___ self = def test_no_error_when_same_userclass_in_two_files(self): with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: MOCK_LOCUSTFILE_CONTENT_C = textwrap.dedent( f""" from {os.path.basename(file1)[:-3]} import TestUser1 """ ) print(MOCK_LOCUSTFILE_CONTENT_C) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file2: > proc = subprocess.Popen( ["locust", "-f", f"{file1},{file2}", "-t", "1", "--headless"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:1173: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpg27usbyc_locustfile.py,/tmp/tmpfjjqipcv_locustfile.py', '-t', '1', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ----------------------------- Captured stdout call ----------------------------- from tmpg27usbyc_locustfile import TestUser1 _____________ StandaloneIntegrationTests.test_percentile_parameter _____________ self = def test_percentile_parameter(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_CHART PERCENTILES_TO_CHART[0] = 0.9 PERCENTILES_TO_CHART[1] = 0.4 class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen( ["locust", "-f", file_path, "--web-port", str(port), "--autostart"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:233: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpoq4zs5i2_locustfile.py', '--web-port', '53681', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ StandaloneIntegrationTests.test_percentiles_to_statistics ___________ self = def test_percentiles_to_statistics(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_STATISTICS PERCENTILES_TO_STATISTICS = [0.9, 0.99] class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen( ["locust", "-f", file_path, "--web-port", str(port), "--autostart"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:259: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp56bkq52l_locustfile.py', '--web-port', '42863', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___ StandaloneIntegrationTests.test_run_autostart_with_multiple_locustfiles ____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_run_autostart_with_multiple_locustfiles(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(dir=temp_dir): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(1) @task def my_task(self): print("running my_task()") """ ), dir=temp_dir, ): > proc = subprocess.Popen( [ "locust", "-f", temp_dir, "--autostart", "-u", "2", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:685: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpc2b3pzg8', '--autostart', '-u', '2', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_run_headless_with_multiple_locustfiles ____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_run_headless_with_multiple_locustfiles(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(dir=temp_dir): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(1) @task def my_task(self): print("running my_task()") """ ), dir=temp_dir, ): > proc = subprocess.Popen( [ "locust", "-f", temp_dir, "--headless", "-u", "2", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:461: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpoak3_3vz', '--headless', '-u', '2', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_run_headless_with_multiple_locustfiles_with_shape _ self = def test_run_headless_with_multiple_locustfiles_with_shape(self): content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( [ "locust", "-f", f"{mocked1.file_path},{mocked2}", "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:565: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993772_7116568_48965.py,/tmp/tmprddfe030_locustfile.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ StandaloneIntegrationTests.test_run_with_userclass_picker ___________ self = def test_run_with_userclass_picker(self): with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_B) as file2: > proc = subprocess.Popen( ["locust", "-f", f"{file1},{file2}", "--class-picker"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpgr_r9984_locustfile.py,/tmp/tmpauz59dx9_locustfile.py', '--class-picker'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_shape_class_log_disabled_parameters ______ self = def test_shape_class_log_disabled_parameters(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "--headless", "-f", mocked.file_path, "--exit-code-on-error=0", "--users=1", "--spawn-rate=1", ] ) locust/test/test_main.py:1252: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '--headless', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993773_1142588_48423.py', '--exit-code-on-error=0', '--users=1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_shape_class_with_use_common_options ______ self = def test_shape_class_with_use_common_options(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): use_common_options = True def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "-f", mocked.file_path, "--run-time=1s", "--users=1", "--spawn-rate=1", "--headless", "--exit-code-on-error=0", ] ) locust/test/test_main.py:1280: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993773_4019156_10660.py', '--run-time=1s', '--users=1', '--spawn-rate=1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___ StandaloneIntegrationTests.test_spawing_with_fixed_multiple_locustfiles ____ self = def test_spawing_with_fixed_multiple_locustfiles(self): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A) as mocked1: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B) as mocked2: proc = subprocess.Popen( " ".join( [ "locust", "-f", f"{mocked1.file_path},{mocked2.file_path}", "--headless", "--run-time", "5s", "-u", "10", "-r", "10", "--loglevel", "INFO", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] > self.assertIn("Ramping to 10 users at a rate of 10.00 per second", output) E AssertionError: 'Ramping to 10 users at a rate of 10.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1022: AssertionError _____________ StandaloneIntegrationTests.test_spawning_with_fixed ______________ self = def test_spawning_with_fixed(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): fixed_count = 2 wait_time = constant(1) @task def t(self): print("Test task is running") class User2(User): wait_time = constant(1) @task def t(self): print("Test task is running") class User3(User): wait_time = constant(1) @task def t(self): print("Test task is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "5s", "-u", "10", "-r", "10", "--loglevel", "INFO", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] > self.assertIn("Ramping to 10 users at a rate of 10.00 per second", output) E AssertionError: 'Ramping to 10 users at a rate of 10.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:987: AssertionError _________________ StandaloneIntegrationTests.test_web_options __________________ self = @unittest.skipIf(platform.system() == "Darwin", reason="Messy on macOS on GH") @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_web_options(self): port = get_free_tcp_port() if platform.system() != "Darwin": # MacOS only sets up the loopback interface for 127.0.0.1 and not for 127.*.*.*, so we cant test this with mock_locustfile() as mocked: > proc = subprocess.Popen( ["locust", "-f", mocked.file_path, "--web-host", "127.0.0.2", "--web-port", str(port)], stdout=PIPE, stderr=PIPE, ) locust/test/test_main.py:838: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993773_930183_98703.py', '--web-host', '127.0.0.2', '--web-port', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________________ StandaloneIntegrationTests.test_webserver ___________________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:206: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpifk3glgf_locustfile.py'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = 82 errwrite = 83, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_webserver_multiple_locustfiles ________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles(self): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A) as mocked1: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B) as mocked2: > proc = subprocess.Popen( ["locust", "-f", f"{mocked1.file_path},{mocked2.file_path}"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:297: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993774_3579144_51693.py,/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993774_3582397_86612.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_webserver_multiple_locustfiles_in_directory __ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles_in_directory(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A, dir=temp_dir): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B, dir=temp_dir): > proc = subprocess.Popen(["locust", "-f", temp_dir], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:314: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpb7h8k6jt'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = 82 errwrite = 83, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_webserver_multiple_locustfiles_with_shape ___ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles_with_shape(self): content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( ["locust", "-f", f"{mocked1.file_path},{mocked2}"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:357: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993774_7620695_35566.py,/tmp/tmp50ci1fvp_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ DistributedIntegrationTests.test_distributed _________________ self = def test_distributed(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-u", "3", "-t", "5s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1570: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993774_9692438_26123.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________ DistributedIntegrationTests.test_distributed_events ______________ self = def test_distributed_events(self): content = ( MOCK_LOCUSTFILE_CONTENT + """ from locust import events from locust.runners import MasterRunner @events.test_start.add_listener def on_test_start(environment, **kwargs): if isinstance(environment.runner, MasterRunner): print("test_start on master") else: print("test_start on worker") @events.test_stop.add_listener def on_test_stop(environment, **kwargs): if isinstance(environment.runner, MasterRunner): print("test_stop on master") else: print("test_stop on worker") """ ) with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-t", "1", "--exit-code-on-error", "0", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1448: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993775_1703234_14389.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ DistributedIntegrationTests.test_distributed_report_timeout_expired ______ self = def test_distributed_report_timeout_expired(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.01" ) as _: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-u", "3", "-t", "5s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1624: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993775_3825676_87655.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______________ DistributedIntegrationTests.test_distributed_tags _______________ self = def test_distributed_tags(self): content = """ from locust import HttpUser, TaskSet, task, between, LoadTestShape, tag class SecondUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(0, 0.1) @tag("tag1") @task def task1(self): print("task1") @tag("tag2") @task def task2(self): print("task2") """ with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-t", "1", "-u", "2", "--exit-code-on-error", "0", "-L", "DEBUG", "--tags", "tag1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1509: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993775_572703_51072.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ DistributedIntegrationTests.test_distributed_with_locustfile_distribution_not_plain_filename _ self = def test_distributed_with_locustfile_distribution_not_plain_filename(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path[:-3], # remove ".py" "--headless", "--master", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1804: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993775_7835763_91612', '--headless', '--master'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ DistributedIntegrationTests.test_expect_workers ________________ self = def test_expect_workers(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "--expect-workers-max-wait", "1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1404: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993775_981756_51474.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ DistributedIntegrationTests.test_json_schema _________________ self = def test_json_schema(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import HttpUser, task, constant class QuickstartUser(HttpUser): wait_time = constant(1) @task def hello_world(self): self.client.get("/") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "http://google.com", "--headless", "-u", "1", "-t", "2s", "--json", ], stderr=DEVNULL, stdout=PIPE, text=True, ) locust/test/test_main.py:1848: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993776_2025814_14447.py', '--host', 'http://google.com', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________ DistributedIntegrationTests.test_locustfile_distribution ___________ self = def test_locustfile_distribution(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "-t", "1s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1679: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993776_4164293_44597.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ DistributedIntegrationTests.test_locustfile_distribution_with_workers_started_first _ self = def test_locustfile_distribution_with_workers_started_first(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): print("hello") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc_worker = subprocess.Popen( [ "locust", "-f", "-", "--worker", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1751: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '-', '--worker'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = -1 errwrite = 81, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________________ DistributedIntegrationTests.test_processes __________________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes(self): with mock_locustfile() as mocked: command = f"locust -f {mocked.file_path} --processes 4 --headless --run-time 1 --exit-code-on-error 0" proc = subprocess.Popen( command, shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, stderr = proc.communicate(timeout=9) except Exception: proc.kill() assert False, f"locust process never finished: {command}" self.assertNotIn("Traceback", stderr) > self.assertIn("(index 3) reported as ready", stderr) E AssertionError: '(index 3) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1993: AssertionError ____________ DistributedIntegrationTests.test_processes_autodetect _____________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_autodetect(self): with mock_locustfile() as mocked: command = f"locust -f {mocked.file_path} --processes -1 --headless --run-time 1 --exit-code-on-error 0" proc = subprocess.Popen( command, shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, stderr = proc.communicate(timeout=9) except Exception: proc.kill() assert False, f"locust process never finished: {command}" self.assertNotIn("Traceback", stderr) > self.assertIn("(index 0) reported as ready", stderr) E AssertionError: '(index 0) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:2013: AssertionError ______________ DistributedIntegrationTests.test_processes_ctrl_c _______________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_ctrl_c(self): with mock_locustfile() as mocked: > proc = psutil.Popen( # use psutil.Popen instead of subprocess.Popen to use extra features [ "locust", "-f", mocked.file_path, "--processes", "4", "--headless", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2064: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/psutil/__init__.py:1378: in __init__ self.__subproc = subprocess.Popen(*args, **kwargs) /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993777_022596_74289.py', '--processes', '4', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ DistributedIntegrationTests.test_processes_error_doesnt_blow_up_completely __ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_error_doesnt_blow_up_completely(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--processes", "4", "-L", "DEBUG", "UserThatDoesntExist", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993777_2686336_36421.py', '--processes', '4', '-L', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ DistributedIntegrationTests.test_processes_separate_worker __________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_separate_worker(self): with mock_locustfile() as mocked: master_proc = subprocess.Popen( f"locust -f {mocked.file_path} --master --headless --run-time 1 --exit-code-on-error 0 --expect-workers-max-wait 2", shell=True, stdout=PIPE, stderr=PIPE, text=True, ) worker_parent_proc = subprocess.Popen( f"locust -f {mocked.file_path} --processes 4 --worker", shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, worker_stderr = worker_parent_proc.communicate(timeout=9) except Exception: master_proc.kill() worker_parent_proc.kill() _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() assert False, f"worker never finished: {worker_stderr}" try: _, master_stderr = master_proc.communicate(timeout=9) except Exception: master_proc.kill() worker_parent_proc.kill() _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() assert False, f"master never finished: {master_stderr}" _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() self.assertNotIn("Traceback", worker_stderr) self.assertNotIn("Traceback", master_stderr) self.assertNotIn("Gave up waiting for workers to connect", master_stderr) > self.assertIn("(index 3) reported as ready", master_stderr) E AssertionError: '(index 3) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:2058: AssertionError ______ DistributedIntegrationTests.test_processes_workers_quit_unexpected ______ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") @unittest.skipIf(sys.platform == "darwin", reason="Flaky on macOS :-/") def test_processes_workers_quit_unexpected(self): content = """ from locust import runners, events, User, task import sys runners.HEARTBEAT_INTERVAL = 0.1 @events.test_start.add_listener def on_test_start(environment, **_kwargs): if isinstance(environment.runner, runners.WorkerRunner): sys.exit(42) class AnyUser(User): @task def mytask(self): pass """ with mock_locustfile(content=content) as mocked: > worker_proc = subprocess.Popen( ["locust", "-f", mocked.file_path, "--processes", "2", "--worker"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2202: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993777_5574439_32608.py', '--processes', '2', '--worker'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ DistributedIntegrationTests.test_worker_indexes ________________ self = def test_worker_indexes(self): content = """ from locust import HttpUser, task, between class AnyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(0, 0.1) @task def my_task(self): print("worker index:", self.environment.runner.worker_index) """ with mock_locustfile(content=content) as mocked: > master = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "-t", "5", "-u", "2", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1900: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993777_7388303_17788.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ DistributedIntegrationTests.test_workers_shut_down_if_master_is_gone _____ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_workers_shut_down_if_master_is_gone(self): content = """ from locust import HttpUser, task, constant, runners runners.MASTER_HEARTBEAT_TIMEOUT = 2 class AnyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = constant(1) @task def my_task(self): print("worker index:", self.environment.runner.worker_index) """ with mock_locustfile(content=content) as mocked: > master_proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--master", "--headless", "--expect-workers", "2", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2115: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710993777_918219_78008.py', '--master', '--headless', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ TestMasterRunner.test_attributes_populated_when_calling_start _________ self = def test_attributes_populated_when_calling_start(self): class MyUser1(User): @task def my_task(self): pass class MyUser2(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser1, MyUser2]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) master.start(7, 7) > self.assertEqual({"MyUser1": 4, "MyUser2": 3}, master.target_user_classes_count) E AssertionError: {'MyUser1': 4, 'MyUser2': 3} != {} E - {'MyUser1': 4, 'MyUser2': 3} E + {} locust/test/test_runners.py:3033: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ________________ TestMasterRunner.test_custom_shape_scale_down _________________ self = def test_custom_shape_scale_down(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return 5, 5 elif run_time < 4: return 1, 5 else: return None self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() sleep(0.5) # Wait for shape_worker to update user_count num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 5, num_users, "Total number of users in first stage of shape test is not 5: %i" % num_users ) E AssertionError: 5 != 0 : Total number of users in first stage of shape test is not 5: 0 locust/test/test_runners.py:2907: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 5 users at 5.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines ______________ TestMasterRunner.test_custom_shape_scale_interval _______________ self = def test_custom_shape_scale_interval(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def __init__(self): super().__init__() self._users_num = [1, 1, 1, 2, 2, 3, 3, 3, 4] self._index = 0 def tick(self): if self._index >= len(self._users_num): return None users_num = self._users_num[self._index] self._index += 1 return users_num, users_num self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() # Wait for shape_worker to update user_count sleep(0.5) num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 1, num_users, "Total number of users in first stage of shape test is not 1: %i" % num_users ) E AssertionError: 1 != 0 : Total number of users in first stage of shape test is not 1: 0 locust/test/test_runners.py:2800: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 1 users at 1.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _________________ TestMasterRunner.test_custom_shape_scale_up __________________ self = def test_custom_shape_scale_up(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return 1, 1 elif run_time < 4: return 2, 2 else: return None self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() sleep(0.5) # Wait for shape_worker to update user_count num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 1, num_users, "Total number of users in first stage of shape test is not 1: %i" % num_users ) E AssertionError: 1 != 0 : Total number of users in first stage of shape test is not 1: 0 locust/test/test_runners.py:2858: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 1 users at 1.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:356 Shape test updating to 1 users at 5.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _____________ TestMasterRunner.test_last_worker_missing_stops_test _____________ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=0.1) def test_last_worker_missing_stops_test(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) server.mocked_send(Message("client_ready", __version__, "fake_client3")) master.start(3, 3) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("spawning", None, "fake_client3")) sleep(0.2) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client1", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client2", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client3", ) ) sleep(0.2) self.assertEqual(0, len(master.clients.missing)) > self.assertEqual(3, master.worker_count) E AssertionError: 3 != 0 locust/test/test_runners.py:2236: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client3. Asking worker to quit. ____________ TestMasterRunner.test_last_worker_quitting_stops_test _____________ self = def test_last_worker_quitting_stops_test(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) master.start(1, 2) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("quit", None, "fake_client1")) sleep(0.1) > self.assertEqual(1, len(master.clients.all)) E AssertionError: 1 != 0 locust/test/test_runners.py:2183: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. ___________ TestMasterRunner.test_master_discard_first_client_ready ____________ self = def test_master_discard_first_client_ready(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: server.mocked_send(Message("client_ready", __version__, "dummy_client")) # discard first client_ready msg server.queue.get() master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "dummy_client")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3148: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (dummy_client). That's not going to work. _________ TestMasterRunner.test_master_marks_downed_workers_as_missing _________ self = def test_master_marks_downed_workers_as_missing(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(6) # print(master.clients['fake_client'].__dict__) > assert master.clients["fake_client"].state == STATE_MISSING locust/test/test_runners.py:2162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , k = 'fake_client' def __getitem__(self, k: str) -> WorkerNode: > return self._worker_nodes[k] E KeyError: 'fake_client' locust/runners.py:636: KeyError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. INFO locust.runners:runners.py:356 Shape test updating to 2 users at 2.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:356 Shape test updating to 2 users at 2.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:342 Shape test stopping INFO locust.runners:runners.py:933 Worker 0 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 1 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 2 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 3 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 4 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:941 The last worker went missing, stopping test. INFO locust.runners:runners.py:342 Shape test stopping INFO locust.runners:runners.py:356 Shape test updating to 3 users at 3.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:356 Shape test updating to 4 users at 4.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ________________ TestMasterRunner.test_master_reset_connection _________________ self = def test_master_reset_connection(self): """Test that connection will be reset when network issues found""" with mock.patch("locust.runners.FALLBACK_INTERVAL", new=0.1): with mock.patch("locust.rpc.rpc.Server", mocked_rpc(raise_on_close=False)) as server: master = self.get_runner() self.assertEqual(0, len(master.clients)) server.mocked_send(Message("client_ready", NETWORK_BROKEN, "fake_client")) self.assertTrue(master.connection_broken) server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(1) self.assertFalse(master.connection_broken) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2998: AssertionError ------------------------------ Captured log call ------------------------------- INFO locust.runners:runners.py:342 Shape test stopping ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. INFO locust.runners:runners.py:959 Resetting RPC server and all worker connections. ________ TestMasterRunner.test_rebalance_locust_users_on_worker_connect ________ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=600) def test_rebalance_locust_users_on_worker_connect(self): class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2511: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. ____________ TestMasterRunner.test_reset_connection_after_RPCError _____________ self = def test_reset_connection_after_RPCError(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc(raise_on_close=False)) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(0.2) self.assertFalse(master.connection_broken) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3007: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. ______________ TestMasterRunner.test_spawn_correct_worker_indexes ______________ self = def test_spawn_correct_worker_indexes(self): """ Tests that workers would receive a monotonic sequence of ordinal IDs. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) USERS_COUNT = 5 for i in range(USERS_COUNT): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(USERS_COUNT, USERS_COUNT) > self.assertEqual(USERS_COUNT * 2, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2753: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ____________ TestMasterRunner.test_spawn_fewer_locusts_than_workers ____________ self = def test_spawn_fewer_locusts_than_workers(self): class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(2, 2) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2726: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected __________________ TestMasterRunner.test_spawn_uneven_locusts __________________ self = def test_spawn_uneven_locusts(self): """ Tests that we can accurately spawn a certain number of locusts, even if it's not an even number of the connected workers """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2705: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ______________________ TestMasterRunner.test_start_event _______________________ self = def test_start_event(self): """ Tests that test_start event is fired """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) run_count = [0] @self.environment.events.test_start.add_listener def on_test_start(*a, **kw): run_count[0] += 1 for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2580: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _______________________ TestMasterRunner.test_stop_event _______________________ self = def test_stop_event(self): """ Tests that test_stop event is fired """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) @self.environment.events.test_stopping.add_listener def on_test_stopping(*_, **__): self.runner_stopping = True @self.environment.events.test_stop.add_listener def on_test_stop(*_, **__): self.runner_stopped = True for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2619: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ____________________ TestMasterRunner.test_stop_event_quit _____________________ self = def test_stop_event_quit(self): """ Tests that test_stop event is fired when quit() is called directly """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) @self.environment.events.test_stopping.add_listener def on_test_stopping(*_, **__): self.runner_stopping = True @self.environment.events.test_stop.add_listener def on_test_stop(*_, **__): self.runner_stopped = True for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2658: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected __________ TestMasterRunner.test_unknown_host_sends_message_to_master __________ self = def test_unknown_host_sends_message_to_master(self): """ Validate master ignores message that is sent from unknown host """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3217: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. _____________________ TestMasterRunner.test_worker_connect _____________________ self = def test_worker_connect(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2083: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. __________ TestMasterRunner.test_worker_connect_with_special_versions __________ self = def test_worker_connect_with_special_versions(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", None, "1.x_style_client_should_not_be_allowed")) self.assertEqual(1, len(self.mocked_log.error)) self.assertEqual(0, len(master.clients)) server.mocked_send(Message("client_ready", "abcd", "other_version_mismatch_should_just_give_a_warning")) self.assertEqual(1, len(self.mocked_log.warning)) self.assertEqual(1, len(master.clients)) server.mocked_send(Message("client_ready", -1, "version_check_bypass_should_not_warn")) self.assertEqual(1, len(self.mocked_log.warning)) self.assertEqual(2, len(master.clients)) server.mocked_send( Message("client_ready", __version__ + "1", "difference_in_patch_version_should_not_warn") ) self.assertEqual(3, len(master.clients)) > self.assertEqual(1, len(self.mocked_log.warning)) E AssertionError: 1 != 2 locust/test/test_runners.py:2111: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (1.x_style_client_should_not_be_allowed). That's not going to work. WARNING locust.runners:runners.py:1017 A worker (other_version_mismatch_should_just_give_a_warning) running a different version (abcd) connected, master version is INFO locust.runners:runners.py:1028 Worker other_version_mismatch_should_just_give_a_warning (index 0) reported as ready. 1 workers connected. INFO locust.runners:runners.py:1028 Worker version_check_bypass_should_not_warn (index 1) reported as ready. 2 workers connected. WARNING locust.runners:runners.py:1017 A worker (difference_in_patch_version_should_not_warn) running a different version (1) connected, master version is INFO locust.runners:runners.py:1028 Worker difference_in_patch_version_should_not_warn (index 2) reported as ready. 3 workers connected. ______ TestMasterRunner.test_worker_missing_after_heartbeat_dead_interval ______ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=0.1) @mock.patch("locust.runners.HEARTBEAT_DEAD_INTERNAL", new=-3) def test_worker_missing_after_heartbeat_dead_interval(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) server.mocked_send(Message("client_ready", __version__, "fake_client3")) master.start(3, 3) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("spawning", None, "fake_client3")) sleep(0.1) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client1", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client2", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client3", ) ) sleep(0.1) # initially all workers are in active state self.assertEqual(0, len(master.clients.missing)) > self.assertEqual(3, master.worker_count) E AssertionError: 3 != 0 locust/test/test_runners.py:2308: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client3. Asking worker to quit. ___________ TestMasterRunner.test_worker_sends_bad_message_to_master ___________ self = def test_worker_sends_bad_message_to_master(self): """ Validate master sends reconnect message to worker when it receives a bad message. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3166: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. ______ TestMasterRunner.test_worker_sends_unrecognized_message_to_master _______ self = def test_worker_sends_unrecognized_message_to_master(self): """ Validate master ignores message from worker when it cannot parse adddress info. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3194: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. _______________________ TestCsvStats.test_stats_history ________________________ self = def test_stats_history(self): env1 = Environment(events=locust.events, catch_exceptions=False) runner1 = env1.create_master_runner("127.0.0.1", 5558) env2 = Environment(events=locust.events, catch_exceptions=False) > runner2 = env2.create_worker_runner("127.0.0.1", 5558) locust/test/test_stats.py:589: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/env.py:153: in create_worker_runner return self._create_runner( locust/env.py:115: in _create_runner self.runner = runner_class(self, *args, **kwargs) locust/runners.py:1216: in __init__ self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def connect_to_master(self): self.retry += 1 self.client.send(Message("client_ready", __version__, self.client_id)) try: success = self.connection_event.wait(timeout=CONNECT_TIMEOUT) except KeyboardInterrupt: # dont complain about getting CTRL-C sys.exit(1) if not success: if self.retry < 3: logger.debug( f"Failed to connect to master {self.master_host}:{self.master_port}, retry {self.retry}/{CONNECT_RETRY_COUNT}." ) else: logger.warning( f"Failed to connect to master {self.master_host}:{self.master_port}, retry {self.retry}/{CONNECT_RETRY_COUNT}." ) if self.retry > CONNECT_RETRY_COUNT: > raise ConnectionError() E ConnectionError locust/runners.py:1444: ConnectionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 3/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 4/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 5/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 6/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 7/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 8/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 9/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 10/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 11/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 12/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 13/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 14/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 15/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 16/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 17/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 18/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 19/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 20/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 21/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 22/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 23/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 24/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 25/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 26/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 27/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 28/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 29/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 30/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 31/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 32/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 33/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 34/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 35/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 36/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 37/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 38/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 39/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 40/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 41/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 42/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 43/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 44/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 45/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 46/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 47/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 48/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 49/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 50/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 51/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 52/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 53/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 54/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 55/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 56/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 57/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 58/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 59/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 60/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_28be9df0e5414139a53073286a84d21a). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 61/60. =============================== warnings summary =============================== locust/test/test_fasthttp.py::TestFastHttpSsl::test_ssl_request_insecure locust/test/test_web.py::TestWebUIWithTLS::test_index_with_https /usr/lib/python3/dist-packages/gevent/ssl.py:238: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated self._context = SSLContext(ssl_version) locust/test/test_log.py: 4 warnings locust/test/test_main.py: 38 warnings /usr/lib/python3/dist-packages/gevent/os.py:426: DeprecationWarning: This process (pid=60739) is multi-threaded, use of fork() may lead to deadlocks in the child. pid = fork() locust/test/test_web.py::TestWebUI::test_html_stats_report locust/test/test_web.py::TestWebUI::test_report_download locust/test/test_web.py::TestWebUI::test_report_exceptions locust/test/test_web.py::TestWebUI::test_report_host locust/test/test_web.py::TestWebUI::test_report_host2 locust/test/test_web.py::TestWebUI::test_report_page locust/test/test_web.py::TestWebUI::test_report_page_empty_stats locust/test/test_web.py::TestModernWebUI::test_html_stats_report /build/reproducible-path/locust-2.24.0/locust/html.py:42: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC). start_time = datetime.datetime.utcfromtimestamp(start_ts).strftime("%Y-%m-%d %H:%M:%S") locust/test/test_web.py::TestWebUI::test_report_download locust/test/test_web.py::TestWebUI::test_report_exceptions locust/test/test_web.py::TestWebUI::test_report_host locust/test/test_web.py::TestWebUI::test_report_host2 locust/test/test_web.py::TestWebUI::test_report_page /build/reproducible-path/locust-2.24.0/locust/html.py:46: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC). end_time = datetime.datetime.utcfromtimestamp(end_ts).strftime("%Y-%m-%d %H:%M:%S") -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ FAILED locust/test/test_http.py::TestHttpSession::test_event_measure - Assert... FAILED locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_from_url FAILED locust/test/test_log.py::TestLoggingOptions::test_log_to_file - OSErro... FAILED locust/test/test_log.py::TestLoggingOptions::test_logging_output - OSE... FAILED locust/test/test_log.py::TestLoggingOptions::test_skip_logging - OSErr... FAILED locust/test/test_log.py::TestLoggingOptions::test_user_broken_on_start FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_load_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_wo_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_command_line_user_selection FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments_in_file FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_exit_code FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_shape_class_names FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_userclass_names FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_locustfiles_directory_is_empty FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_no_tasks_match_tags FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_providing_both_run_time_and_a_shape_class FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_graceful_exit_when_keyboard_interrupt FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_headless_spawn_options_wo_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_help_arg - ... FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_html_report_option FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_input - Ass... FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_percentile_parameter FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_stop_timeout_string FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_no_error_when_same_userclass_in_two_files FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_percentile_parameter FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_percentiles_to_statistics FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_autostart_with_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_with_userclass_picker FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_log_disabled_parameters FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_with_use_common_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_spawing_with_fixed_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_spawning_with_fixed FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_web_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_in_directory FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_events FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_report_timeout_expired FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_tags FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_with_locustfile_distribution_not_plain_filename FAILED locust/test/test_main.py::DistributedIntegrationTests::test_expect_workers FAILED locust/test/test_main.py::DistributedIntegrationTests::test_json_schema FAILED locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution FAILED locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution_with_workers_started_first FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_autodetect FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_ctrl_c FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_error_doesnt_blow_up_completely FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_separate_worker FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_workers_quit_unexpected FAILED locust/test/test_main.py::DistributedIntegrationTests::test_worker_indexes FAILED locust/test/test_main.py::DistributedIntegrationTests::test_workers_shut_down_if_master_is_gone FAILED locust/test/test_runners.py::TestMasterRunner::test_attributes_populated_when_calling_start FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_down FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_interval FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_up FAILED locust/test/test_runners.py::TestMasterRunner::test_last_worker_missing_stops_test FAILED locust/test/test_runners.py::TestMasterRunner::test_last_worker_quitting_stops_test FAILED locust/test/test_runners.py::TestMasterRunner::test_master_discard_first_client_ready FAILED locust/test/test_runners.py::TestMasterRunner::test_master_marks_downed_workers_as_missing FAILED locust/test/test_runners.py::TestMasterRunner::test_master_reset_connection FAILED locust/test/test_runners.py::TestMasterRunner::test_rebalance_locust_users_on_worker_connect FAILED locust/test/test_runners.py::TestMasterRunner::test_reset_connection_after_RPCError FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_correct_worker_indexes FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_fewer_locusts_than_workers FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_uneven_locusts FAILED locust/test/test_runners.py::TestMasterRunner::test_start_event - Asse... FAILED locust/test/test_runners.py::TestMasterRunner::test_stop_event - Asser... FAILED locust/test/test_runners.py::TestMasterRunner::test_stop_event_quit - ... FAILED locust/test/test_runners.py::TestMasterRunner::test_unknown_host_sends_message_to_master FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_connect - A... FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_connect_with_special_versions FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_missing_after_heartbeat_dead_interval FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_sends_bad_message_to_master FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_sends_unrecognized_message_to_master FAILED locust/test/test_stats.py::TestCsvStats::test_stats_history - Connecti... = 85 failed, 463 passed, 1 skipped, 15 deselected, 57 warnings in 535.37s (0:08:55) = E: pybuild pybuild:389: test: plugin custom failed with: exit code=1: PYTHONPATH=/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.12_locust/build python3.12 -m pytest -v --ignore=examples/test_data_management.py -k 'not TestMasterWorkerRunners' I: pybuild base:305: PYTHONPATH=/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.11_locust/build python3.11 -m pytest -v --ignore=examples/test_data_management.py -k 'not TestMasterWorkerRunners' ============================= test session starts ============================== platform linux -- Python 3.11.8, pytest-8.1.1, pluggy-1.4.0 -- /usr/bin/python3.11 cachedir: .pytest_cache rootdir: /build/reproducible-path/locust-2.24.0 configfile: pyproject.toml collecting ... collected 564 items / 15 deselected / 549 selected locust/test/test_debugging.py::TestDebugging::test_run_single_user_pass_host_to_user_classes PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_0_5 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_1 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_2 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_2_4 PASSED [ 0%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_3 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_4 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_3_workers_with_spawn_rate_of_9 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_ramp_up_users_to_4_workers_with_spawn_rate_of_1 PASSED [ 1%] locust/test/test_dispatch.py::TestRampUpUsersFromZero::test_users_are_distributed_evenly_across_hosts PASSED [ 1%] locust/test/test_dispatch.py::TestWaitBetweenDispatch::test_wait_between_dispatch PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_0_5 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_1 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_2 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_2_4 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_3 PASSED [ 2%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_4 PASSED [ 3%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_3_workers_with_spawn_rate_of_9 PASSED [ 3%] locust/test/test_dispatch.py::TestRampDownUsersToZero::test_ramp_down_users_to_4_workers_with_spawn_rate_of_1 PASSED [ 3%] locust/test/test_dispatch.py::TestRampUpThenDownThenUp::test_ramp_up_then_down_then_up SKIPPED [ 3%] locust/test/test_dispatch.py::TestDispatchUsersToWorkersHavingTheSameUsersAsTheTarget::test_dispatch_users_to_3_workers PASSED [ 3%] locust/test/test_dispatch.py::TestDistributionIsRespectedDuringDispatch::test_dispatch_75_users_to_4_workers_with_spawn_rate_of_5 PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_distribute_users PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_ramp_down_from_100_000_to_0_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate PASSED [ 4%] locust/test/test_dispatch.py::TestLargeScale::test_ramp_up_from_0_to_100_000_users_with_50_user_classes_and_1000_workers_and_5000_spawn_rate PASSED [ 4%] locust/test/test_dispatch.py::TestSmallConsecutiveRamping::test_consecutive_ramp_up_and_ramp_down PASSED [ 4%] locust/test/test_dispatch.py::TestRampingMiscellaneous::test_spawn_rate_greater_than_target_user_count PASSED [ 4%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_last_worker PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_between_two_ramp_ups PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_during_ramp_down PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_two_workers_during_ramp_up PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_between_two_ramp_ups PASSED [ 5%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_down PASSED [ 6%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_up PASSED [ 6%] locust/test/test_dispatch.py::TestRemoveWorker::test_remove_worker_during_ramp_up_with_fixed_user PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_between_two_ramp_ups PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_during_ramp_down PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_two_workers_during_ramp_up PASSED [ 6%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_between_two_ramp_ups PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_down PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_up PASSED [ 7%] locust/test/test_dispatch.py::TestAddWorker::test_add_worker_during_ramp_up_with_fixed_user PASSED [ 7%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_2_weigted_user_with_1_fixed_user PASSED [ 7%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_only_fixed_users PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_partially_ramp_down_and_rump_up_to_target PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_ramp_down_and_ramp_up_again PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_ramp_down_and_ramp_up_again_single_fixed_class PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpUsersFromZeroWithFixed::test_ramp_up_various_count_weigted_and_fixed_users PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_add_worker_during_ramp_up_custom_classes PASSED [ 8%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_down_custom_user_classes_respect_weighting PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_different_users_each_dispatch_multiple_worker PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_different_users_for_each_dispatch PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_first_half_user1_second_half_user2 PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_first_one_user_then_all_classes PASSED [ 9%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_one_user_class_multiple_worker PASSED [ 10%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_ramp_up_only_one_kind_of_user PASSED [ 10%] locust/test/test_dispatch.py::TestRampUpDifferentUsers::test_remove_worker_during_ramp_up_custom_classes PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_all_user_classes_with_zero_weight_raises_exception PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_assign_equal_weights PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_dispatcher_class_attribute PASSED [ 10%] locust/test/test_env.py::TestEnvironment::test_shape_class_attribute PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_update_user_class PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_count PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_with_same_name_is_error PASSED [ 11%] locust/test/test_env.py::TestEnvironment::test_user_classes_with_zero_weight_are_removed PASSED [ 11%] locust/test/test_fasthttp.py::TestFastHttpSession::test_204 PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_404 PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_default_fail PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_default_success PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_fail_successful_request PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_multiple_failure_and_success PASSED [ 12%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_pass_failed_request PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_catch_response_pass_failed_request_with_other_exception_within_block PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_connection_error PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_cookie PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_custom_ssl_context_fail_with_bad_context PASSED [ 13%] locust/test/test_fasthttp.py::TestFastHttpSession::test_custom_ssl_context_passed_correct_to_client_pool PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_delete PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_error_message_with_name_replacement PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_get PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_head PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_json_payload PASSED [ 14%] locust/test/test_fasthttp.py::TestFastHttpSession::test_options PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_patch PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_post_redirect PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_slow_redirect PASSED [ 15%] locust/test/test_fasthttp.py::TestFastHttpSession::test_streaming_response PASSED [ 15%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_connection_error PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_content_length PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length_streaming PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_put PASSED [ 16%] locust/test/test_fasthttp.py::TestRequestStatsWithWebserver::test_request_stats_query_variables PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_allow_redirects_override PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_class_context PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_basic_auth PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_delete PASSED [ 17%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_get PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_get_absolute_url PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_head PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_pool_concurrency PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_pool_per_user_instance PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_post PASSED [ 18%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_put PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_client_request_headers PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_complex_content_type PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_get_request PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_is_abstract PASSED [ 19%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_log_request_name_argument PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_max_redirect_setting PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_network_timeout_setting PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_redirect_url_original_path_as_name PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_shared_client_pool PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpUserClass::test_slow_redirect PASSED [ 20%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_allow_404 PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_connection_error_fail PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_connection_error_success PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_fail PASSED [ 21%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_manual_fail PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_http_manual_success PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_catch_response_missing_with_block PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_interrupt_taskset_with_catch_response PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_missing_catch_response_true PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_rest_fail PASSED [ 22%] locust/test/test_fasthttp.py::TestFastHttpCatchResponse::test_rest_success PASSED [ 23%] locust/test/test_fasthttp.py::TestFastHttpSsl::test_ssl_request_insecure PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_default_fail PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_default_success PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_fail_successful_request PASSED [ 23%] locust/test/test_http.py::TestHttpSession::test_catch_response_fail_successful_request_with_non_string_error_message PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_missing_with_block PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_multiple_failure_and_success PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_pass_failed_request PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_pass_failed_request_with_other_exception_within_block PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_response_error PASSED [ 24%] locust/test/test_http.py::TestHttpSession::test_catch_response_timeout PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_catch_response_with_name_replacement PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_connection_error PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_context_in_success PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_cookie PASSED [ 25%] locust/test/test_http.py::TestHttpSession::test_delete PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_error_message PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_error_message_with_name_replacement PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_event_measure PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_get PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_get_with_params PASSED [ 26%] locust/test/test_http.py::TestHttpSession::test_head PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_missing_catch_response_true PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_options PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_post_redirect PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_response_parameter PASSED [ 27%] locust/test/test_http.py::TestHttpSession::test_slow_redirect PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_streaming_response PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_user_context PASSED [ 28%] locust/test/test_http.py::TestHttpSession::test_wrong_url PASSED [ 28%] locust/test/test_interruptable_task.py::TestInterruptableTask::test_interruptable_task PASSED [ 28%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_command_line_arguments_override_config_file PASSED [ 28%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_create_environment PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_is_user_class PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_called_locust_dot_py PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_from_absolute_path PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_from_relative_path PASSED [ 29%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_load_locust_file_with_a_dot_in_filename PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_can_be_set_in_config_file PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_from_url FAILED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_return_docstring_and_user_classes PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_specify_config_file PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_abstract_shape_class PASSED [ 30%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_multiple_shape_classes PASSED [ 31%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_not_imported_shape_class PASSED [ 31%] locust/test/test_load_locustfile.py::TestLoadLocustfile::test_with_shape_class PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_start PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_start_interrupt PASSED [ 31%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_interrupt PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_interrupt_reschedule PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_on_stop_when_locust_stops PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_parent_attribute PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_schedule_task PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_schedule_task_bound_method PASSED [ 32%] locust/test/test_locust_class.py::TestTaskSet::test_sub_taskset PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_sub_taskset_tasks_decorator PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_on_taskset PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_ratio PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_decorator_with_or_without_argument PASSED [ 33%] locust/test/test_locust_class.py::TestTaskSet::test_task_ratio PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_missing_from_user_gives_user_friendly_exception PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_missing_gives_user_friendly_exception PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_on_abstract_locust PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_tasks_on_locust PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_taskset_inheritance PASSED [ 34%] locust/test/test_locust_class.py::TestTaskSet::test_taskset_on_abstract_locust PASSED [ 35%] locust/test/test_locust_class.py::TestTaskSet::test_user_is_read_only PASSED [ 35%] locust/test/test_locust_class.py::TestTaskSet::test_wait_function PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_deprecated_locust_class PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_locust_forced_stop PASSED [ 35%] locust/test/test_locust_class.py::TestLocustClass::test_locust_graceful_stop PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_on_start PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_on_stop PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_start PASSED [ 36%] locust/test/test_locust_class.py::TestLocustClass::test_locust_wait PASSED [ 36%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_basic_auth PASSED [ 36%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_delete PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_get PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_get_absolute_url PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_head PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_post PASSED [ 37%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_put PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_client_request_headers PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_get_request PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_log_request_name_argument PASSED [ 38%] locust/test/test_locust_class.py::TestWebLocustClass::test_redirect_url_original_path_as_name PASSED [ 38%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response PASSED [ 38%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_allow_404 PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_connection_error_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_connection_error_success PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_manual_fail PASSED [ 39%] locust/test/test_locust_class.py::TestCatchResponse::test_catch_response_http_manual_success PASSED [ 40%] locust/test/test_locust_class.py::TestCatchResponse::test_interrupt_taskset_with_catch_response PASSED [ 40%] locust/test/test_log.py::TestGreenletExceptionLogger::test_greenlet_exception_logger PASSED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_log_to_file FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_logging_output FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_skip_logging FAILED [ 40%] locust/test/test_log.py::TestLoggingOptions::test_user_broken_on_start FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_multiple_locustfiles_with_shape FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_load_shape FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_run_time FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_wo_run_time FAILED [ 41%] locust/test/test_main.py::StandaloneIntegrationTests::test_command_line_user_selection FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments_in_file FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_custom_exit_code FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options_with_shape FAILED [ 42%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_shape_class_names FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_userclass_names FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_locustfiles_directory_is_empty FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_no_tasks_match_tags FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_providing_both_run_time_and_a_shape_class FAILED [ 43%] locust/test/test_main.py::StandaloneIntegrationTests::test_graceful_exit_when_keyboard_interrupt FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_headless_spawn_options_wo_run_time FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_help_arg FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_html_report_option FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_input FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_percentile_parameter FAILED [ 44%] locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_stop_timeout_string FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_no_error_when_same_userclass_in_two_files FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_percentile_parameter FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_percentiles_to_statistics FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_autostart_with_multiple_locustfiles FAILED [ 45%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles_with_shape FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_run_with_userclass_picker FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_log_disabled_parameters FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_with_use_common_options FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_spawing_with_fixed_multiple_locustfiles FAILED [ 46%] locust/test/test_main.py::StandaloneIntegrationTests::test_spawning_with_fixed FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_web_options FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_in_directory FAILED [ 47%] locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_with_shape FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_events FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_report_timeout_expired FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_tags FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_distributed_with_locustfile_distribution_not_plain_filename FAILED [ 48%] locust/test/test_main.py::DistributedIntegrationTests::test_expect_workers FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_json_schema FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution_with_workers_started_first FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_processes FAILED [ 49%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_autodetect FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_ctrl_c FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_error_doesnt_blow_up_completely FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_separate_worker FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_processes_workers_quit_unexpected FAILED [ 50%] locust/test/test_main.py::DistributedIntegrationTests::test_worker_indexes FAILED [ 51%] locust/test/test_main.py::DistributedIntegrationTests::test_workers_shut_down_if_master_is_gone FAILED [ 51%] locust/test/test_parser.py::TestParser::test_default PASSED [ 51%] locust/test/test_parser.py::TestParser::test_parse_options_from_conf_file PASSED [ 51%] locust/test/test_parser.py::TestParser::test_parse_options_from_toml_file PASSED [ 51%] locust/test/test_parser.py::TestParser::test_reset_stats PASSED [ 51%] locust/test/test_parser.py::TestParser::test_skip_log_setup PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_csv_full_history_requires_csv PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument_help_message PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_custom_argument_included_in_web_ui PASSED [ 52%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_empty_directory_error PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_invalid_directory_error PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_multiple_files PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_directory PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_directory_ignores_invalid_filenames PASSED [ 53%] locust/test/test_parser.py::TestArgumentParser::test_parse_locustfile_with_nested_directory PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_parse_options PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_parse_options_from_env PASSED [ 54%] locust/test/test_parser.py::TestArgumentParser::test_unknown_command_line_arg PASSED [ 54%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_for_invalid_file_extension PASSED [ 54%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_directory_doesnt_exist PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_invalid_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_error_if_multiple_values_for_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_ignores_invalid_files_in_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_with_is_directory PASSED [ 55%] locust/test/test_parser.py::TestFindLocustfiles::test_find_locustfiles_with_multiple_locustfiles PASSED [ 55%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_false_if_file_and_directory_share_the_same_name PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_multiple_locustfiles PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_single_locustfile PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_single_locustfile_without_file_extension PASSED [ 56%] locust/test/test_parser.py::TestLocustfileIsDirectory::test_locustfile_is_directory_true_if_directory PASSED [ 56%] locust/test/test_runners.py::TestLocustRunner::test_attributes_populated_when_calling_start PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_can_call_stop_endpoint_if_currently_swarming PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_change_user_count_during_spawning PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_cpu_warning PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_custom_dispatcher_class PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_custom_message PASSED [ 57%] locust/test/test_runners.py::TestLocustRunner::test_duplicate_message_handler_registration PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_host_class_attribute_from_web PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_kill_locusts PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_no_reset_stats PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_reset_stats PASSED [ 58%] locust/test/test_runners.py::TestLocustRunner::test_runner_quit_can_run_on_stop_for_multiple_users_concurrently PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_runner_reference_on_environment PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_start_event PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event_quit PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_event_stop_and_quit PASSED [ 59%] locust/test/test_runners.py::TestLocustRunner::test_stop_users_count PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_stop_users_with_spawn_rate PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_stopping_event PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_swarm_endpoint_is_non_blocking PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_target_user_count_is_set_before_ramp_up PASSED [ 60%] locust/test/test_runners.py::TestLocustRunner::test_undefined_custom_message PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_user_classes_count PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_user_count_starts_from_specified_amount_when_creating_new_test_after_previous_step_has_been_stopped PASSED [ 61%] locust/test/test_runners.py::TestLocustRunner::test_users_can_call_runner_quit_without_deadlocking PASSED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_attributes_populated_when_calling_start FAILED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_custom_message_receive PASSED [ 61%] locust/test/test_runners.py::TestMasterRunner::test_custom_message_send PASSED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_down FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_interval FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_up FAILED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_exception_in_task PASSED [ 62%] locust/test/test_runners.py::TestMasterRunner::test_exception_is_caught PASSED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_last_worker_missing_stops_test FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_last_worker_quitting_stops_test FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_current_response_times PASSED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_discard_first_client_ready FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_marks_downed_workers_as_missing FAILED [ 63%] locust/test/test_runners.py::TestMasterRunner::test_master_reset_connection FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_master_total_stats PASSED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_master_total_stats_with_none_response_times PASSED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_rebalance_locust_users_on_worker_connect FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_reset_connection_after_RPCError FAILED [ 64%] locust/test/test_runners.py::TestMasterRunner::test_sends_spawn_data_to_ready_running_spawning_workers PASSED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_correct_worker_indexes FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_fewer_locusts_than_workers FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_uneven_locusts FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_spawn_zero_locusts PASSED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_start_event FAILED [ 65%] locust/test/test_runners.py::TestMasterRunner::test_stop_event FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_stop_event_quit FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_undefined_custom_message_receive PASSED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_unknown_host_sends_message_to_master FAILED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_wait_for_workers_report_after_ramp_up PASSED [ 66%] locust/test/test_runners.py::TestMasterRunner::test_worker_connect FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_connect_with_special_versions FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_missing_after_heartbeat_dead_interval FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_sends_bad_message_to_master FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_sends_unrecognized_message_to_master FAILED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_stats_report_median PASSED [ 67%] locust/test/test_runners.py::TestMasterRunner::test_worker_stats_report_with_none_response_times PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_change_user_count_during_spawning PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_computed_properties PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_custom_message_receive PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_custom_message_send PASSED [ 68%] locust/test/test_runners.py::TestWorkerRunner::test_reset_rpc_connection_to_master PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_spawn_message_with_older_timestamp_is_rejected PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_start_event PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_stop_event PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_undefined_custom_message_receive PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_worker_connect_failure PASSED [ 69%] locust/test/test_runners.py::TestWorkerRunner::test_worker_connect_success PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_heartbeat_messages_sent_to_master PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_messages_sent_to_master PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_stop_timeout PASSED [ 70%] locust/test/test_runners.py::TestWorkerRunner::test_worker_without_stop_timeout PASSED [ 70%] locust/test/test_runners.py::TestMessageSerializing::test_message_serialize PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_gracefully_handle_exceptions_in_listener PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_kill_locusts_with_stop_timeout PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_during_on_start PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_exit_during_wait PASSED [ 71%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_interrupt PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_interrupt_no_reschedule PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_stop_timeout_with_ramp_down PASSED [ 72%] locust/test/test_runners.py::TestStopTimeout::test_users_can_call_runner_quit_with_stop_timeout PASSED [ 72%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_multiple_iterations PASSED [ 72%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_inheritance PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_list PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_methods PASSED [ 73%] locust/test/test_sequential_taskset.py::TestTaskSet::test_task_sequence_with_methods_and_list PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation_last_request_timestamp PASSED [ 73%] locust/test/test_stats.py::TestRequestStats::test_aggregation_min_response_time PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_aggregation_with_decimal_rounding PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_aggregation_with_rounding PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_avg PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_avg_only_none PASSED [ 74%] locust/test/test_stats.py::TestRequestStats::test_current_fail_per_sec PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_current_rps PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_custom_percentile_list PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_error_grouping PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_error_grouping_errors_with_memory_addresses PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_median PASSED [ 75%] locust/test/test_stats.py::TestRequestStats::test_median_out_of_min_max_bounds PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_num_reqs_fails PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile_rounded_down PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_percentile_rounded_up PASSED [ 76%] locust/test/test_stats.py::TestRequestStats::test_reset PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_reset_min_response_time PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_rps_less_than_one_second PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_serialize_through_message PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_total_content_length PASSED [ 77%] locust/test/test_stats.py::TestRequestStats::test_total_rps PASSED [ 77%] locust/test/test_stats.py::TestStatsPrinting::test_print_error_report PASSED [ 78%] locust/test/test_stats.py::TestStatsPrinting::test_print_percentile_stats PASSED [ 78%] locust/test/test_stats.py::TestStatsPrinting::test_print_stats PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_on_master_from_aggregated_stats PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_writer PASSED [ 78%] locust/test/test_stats.py::TestCsvStats::test_csv_stats_writer_full_history PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_requests_csv_quote_escaping PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_stats_history FAILED [ 79%] locust/test/test_stats.py::TestCsvStats::test_user_count_in_csv_history_stats PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_write_csv_files PASSED [ 79%] locust/test/test_stats.py::TestCsvStats::test_write_csv_files_full_history PASSED [ 79%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_diff_response_times_dicts PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_get_current_response_time_percentile PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_get_current_response_time_percentile_outside_cache_window PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_latest_total_response_times_pruned PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_response_times_cached PASSED [ 80%] locust/test/test_stats.py::TestStatsEntryResponseTimesCache::test_response_times_not_cached_if_not_enabled PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_all_failures PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_half_failures PASSED [ 81%] locust/test/test_stats.py::TestStatsEntry::test_fail_ratio_with_no_failures PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_connection_error PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_content_length PASSED [ 81%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint_rename_request PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_named_endpoint_request_name PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_no_content_length_streaming PASSED [ 82%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_put PASSED [ 83%] locust/test/test_stats.py::TestRequestStatsWithWebserver::test_request_stats_query_variables PASSED [ 83%] locust/test/test_stats.py::TestInspectUser::test_get_task_ratio_relative PASSED [ 83%] locust/test/test_stats.py::TestInspectUser::test_get_task_ratio_total PASSED [ 83%] locust/test/test_tags.py::TestTags::test_env_exclude_tags PASSED [ 83%] locust/test/test_tags.py::TestTags::test_env_include_tags PASSED [ 83%] locust/test/test_tags.py::TestTags::test_exclude_tags_under_user PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tags PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tags_with_weights PASSED [ 84%] locust/test/test_tags.py::TestTags::test_excluding_tasksets PASSED [ 84%] locust/test/test_tags.py::TestTags::test_include_tags_under_user PASSED [ 84%] locust/test/test_tags.py::TestTags::test_including_and_excluding PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tags PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tags_with_weights PASSED [ 85%] locust/test/test_tags.py::TestTags::test_including_tasksets PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagged_tasks_shared_across_tasksets PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagging PASSED [ 85%] locust/test/test_tags.py::TestTags::test_tagging_taskset PASSED [ 86%] locust/test/test_tags.py::TestTags::test_tagging_without_args_fails PASSED [ 86%] locust/test/test_taskratio.py::TestTaskRatio::test_task_ratio_command PASSED [ 86%] locust/test/test_taskratio.py::TestTaskRatio::test_task_ratio_command_with_locust_weight PASSED [ 86%] locust/test/test_users.py::TestUserClass::test_fullname_class_scoped PASSED [ 86%] locust/test/test_users.py::TestUserClass::test_fullname_function_scoped PASSED [ 87%] locust/test/test_users.py::TestUserClass::test_fullname_module_scoped PASSED [ 87%] locust/test/test_users.py::TestHttpUserWithWebserver::test_pool_manager_per_user_instance PASSED [ 87%] locust/test/test_users.py::TestHttpUserWithWebserver::test_shared_pool_manager PASSED [ 87%] locust/test/test_util.py::TestParseTimespan::test_parse_timespan PASSED [ 87%] locust/test/test_util.py::TestParseTimespan::test_parse_timespan_invalid_values PASSED [ 87%] locust/test/test_util.py::TestRounding::test_rounding_down PASSED [ 88%] locust/test/test_util.py::TestRounding::test_rounding_up PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_between PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_constant PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_constant_throughput PASSED [ 88%] locust/test/test_wait_time.py::TestWaitTime::test_default_wait_time PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_argument_dropdown PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_shape_deactivate_num_users_and_spawn_rate PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_custom_shape_with_use_common_options_keep_num_users_and_spawn_rate PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_exceptions PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_exceptions_csv PASSED [ 89%] locust/test/test_web.py::TestWebUI::test_failure_stats_csv PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_multiple_user_classes PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_multiple_user_classes_different_hosts PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_host_value_from_user_class PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_html_stats_report PASSED [ 90%] locust/test/test_web.py::TestWebUI::test_index PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_index_with_spawn_options PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_logs PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_download PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_exceptions PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_host PASSED [ 91%] locust/test/test_web.py::TestWebUI::test_report_host2 PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_report_page PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_report_page_empty_stats PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_csv PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_full_history_csv_not_present PASSED [ 92%] locust/test/test_web.py::TestWebUI::test_request_stats_with_errors PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_reset_stats PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_cache PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_no_data PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_stats_rounding PASSED [ 93%] locust/test/test_web.py::TestWebUI::test_swarm_custom_argument PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_defaults_to_all_available_userclasses_when_userclass_picker_is_active_and_no_userclass_in_payload PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_error_when_userclass_picker_is_active_but_no_available_userclasses PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_host_value_not_specified PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_host_value_specified PASSED [ 94%] locust/test/test_web.py::TestWebUI::test_swarm_multiple_userclasses_specified PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time_empty_input PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_run_time_invalid_input PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_defaults_to_none_when_userclass_picker_is_active PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_is_updated_when_userclass_picker_is_active PASSED [ 95%] locust/test/test_web.py::TestWebUI::test_swarm_shape_class_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_updates_parsed_options_when_multiple_userclasses_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_updates_parsed_options_when_single_userclass_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_userclass_shapeclass_ignored_when_userclass_picker_is_inactive PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_userclass_specified PASSED [ 96%] locust/test/test_web.py::TestWebUI::test_swarm_uses_pre_selected_user_classes_when_empty_payload_and_test_is_already_running_with_class_picker PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_template_args PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_update_user_endpoint PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_web_ui_no_runner PASSED [ 97%] locust/test/test_web.py::TestWebUI::test_web_ui_reference_on_environment PASSED [ 97%] locust/test/test_web.py::TestWebUIAuth::test_index_with_web_login_enabled_no_user PASSED [ 97%] locust/test/test_web.py::TestWebUIAuth::test_index_with_web_login_enabled_valid_user PASSED [ 98%] locust/test/test_web.py::TestWebUIWithTLS::test_index_with_https PASSED [ 98%] locust/test/test_web.py::TestWebUIFullHistory::test_request_stats_full_history_csv PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_html_stats_report PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_index_with_modern_ui PASSED [ 98%] locust/test/test_web.py::TestModernWebUI::test_web_ui_no_runner PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_recv PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_retry PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_client_send PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_constructor PASSED [ 99%] locust/test/test_zmqrpc.py::ZMQRPC_tests::test_rpc_error PASSED [100%] =================================== FAILURES =================================== _________________ TestLoadLocustfile.test_locustfile_from_url __________________ self = def _new_conn(self): """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ extra_kw = {} if self.source_address: extra_kw["source_address"] = self.source_address if self.socket_options: extra_kw["socket_options"] = self.socket_options try: > conn = connection.create_connection( (self._dns_host, self.port), self.timeout, **extra_kw ) /usr/lib/python3/dist-packages/urllib3/connection.py:174: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/util/connection.py:73: in create_connection for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM): /usr/lib/python3/dist-packages/gevent/_socketcommon.py:225: in getaddrinfo addrlist = get_hub().resolver.getaddrinfo(host, port, family, type, proto, flags) /usr/lib/python3/dist-packages/gevent/resolver/thread.py:63: in getaddrinfo return self.pool.apply(_socket.getaddrinfo, args, kwargs) /usr/lib/python3/dist-packages/gevent/pool.py:161: in apply return self.spawn(func, *args, **kwds).get() src/gevent/event.py:329: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:359: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:347: in gevent._gevent_cevent.AsyncResult.get ??? src/gevent/event.py:327: in gevent._gevent_cevent.AsyncResult._raise_exception ??? /usr/lib/python3/dist-packages/gevent/_compat.py:49: in reraise raise value.with_traceback(tb) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ # Copyright (c) 2012 Denis Bilenko. See LICENSE for details. from __future__ import absolute_import from __future__ import division from __future__ import print_function import os import sys from greenlet import greenlet as RawGreenlet from gevent import monkey from gevent._compat import integer_types from gevent.event import AsyncResult from gevent.exceptions import InvalidThreadUseError from gevent.greenlet import Greenlet from gevent._hub_local import get_hub_if_exists from gevent.hub import _get_hub_noargs as get_hub from gevent.hub import getcurrent from gevent.hub import sleep from gevent.lock import Semaphore from gevent.pool import GroupMappingMixin from gevent.util import clear_stack_frames from gevent._threading import Queue from gevent._threading import EmptyTimeout from gevent._threading import start_new_thread from gevent._threading import get_thread_ident __all__ = [ 'ThreadPool', 'ThreadResult', ] def _format_hub(hub): if hub is None: return '' return '<%s at 0x%x thread_ident=0x%x>' % ( hub.__class__.__name__, id(hub), hub.thread_ident ) def _get_thread_profile(_sys=sys): if 'threading' in _sys.modules: return _sys.modules['threading']._profile_hook def _get_thread_trace(_sys=sys): if 'threading' in _sys.modules: return _sys.modules['threading']._trace_hook class _WorkerGreenlet(RawGreenlet): # Exists to produce a more useful repr for worker pool # threads/greenlets, and manage the communication of the worker # thread with the threadpool. # Inform the gevent.util.GreenletTree that this should be # considered the root (for printing purposes) greenlet_tree_is_root = True _thread_ident = 0 _exc_info = sys.exc_info _get_hub_if_exists = staticmethod(get_hub_if_exists) # We capture the hub each time through the loop in case its created # so we can destroy it after a fork. _hub_of_worker = None # The hub of the threadpool we're working for. Just for info. _hub = None # A cookie passed to task_queue.get() _task_queue_cookie = None # If not -1, how long to block waiting for a task before we # exit. _idle_task_timeout = -1 def __init__(self, threadpool): # Construct in the main thread (owner of the threadpool) # The parent greenlet and thread identifier will be set once the # new thread begins running. RawGreenlet.__init__(self) self._hub = threadpool.hub # Avoid doing any imports in the background thread if it's not # necessary (monkey.get_original imports if not patched). # Background imports can hang Python 2 (gevent's thread resolver runs in the BG, # and resolving may have to import the idna module, which needs an import lock, so # resolving at module scope) if monkey.is_module_patched('sys'): stderr = monkey.get_original('sys', 'stderr') else: stderr = sys.stderr self._stderr = stderr # We can capture the task_queue; even though it can change if the threadpool # is re-innitted, we won't be running in that case self._task_queue = threadpool.task_queue # type:gevent._threading.Queue self._task_queue_cookie = self._task_queue.allocate_cookie() self._unregister_worker = threadpool._unregister_worker self._idle_task_timeout = threadpool._idle_task_timeout threadpool._register_worker(self) try: start_new_thread(self._begin, ()) except: self._unregister_worker(self) raise def _begin(self, _get_c=getcurrent, _get_ti=get_thread_ident): # Pass arguments to avoid accessing globals during module shutdown. # we're in the new thread (but its root greenlet). Establish invariants and get going # by making this the current greenlet. self.parent = _get_c() # pylint:disable=attribute-defined-outside-init self._thread_ident = _get_ti() # ignore the parent attribute. (We can't set parent to None.) self.parent.greenlet_tree_is_ignored = True try: self.switch() # goto run() except: # pylint:disable=bare-except # run() will attempt to print any exceptions, but that might # not work during shutdown. sys.excepthook and such may be gone, # so things might not get printed at all except for a cryptic # message. This is especially true on Python 2 (doesn't seem to be # an issue on Python 3). pass def __fixup_hub_before_block(self): hub = self._get_hub_if_exists() # Don't create one; only set if a worker function did it if hub is not None: hub.name = 'ThreadPool Worker Hub' # While we block, don't let the monitoring thread, if any, # report us as blocked. Indeed, so long as we never # try to switch greenlets, don't report us as blocked--- # the threadpool is *meant* to run blocking tasks if hub is not None and hub.periodic_monitoring_thread is not None: hub.periodic_monitoring_thread.ignore_current_greenlet_blocking() self._hub_of_worker = hub @staticmethod def __print_tb(tb, stderr): # Extracted from traceback to avoid accessing any module # globals (these sometimes happen during interpreter shutdown; # see test__subprocess_interrupted) while tb is not None: f = tb.tb_frame lineno = tb.tb_lineno co = f.f_code filename = co.co_filename name = co.co_name print(' File "%s", line %d, in %s' % (filename, lineno, name), file=stderr) tb = tb.tb_next def _before_run_task(self, func, args, kwargs, thread_result, _sys=sys, _get_thread_profile=_get_thread_profile, _get_thread_trace=_get_thread_trace): # pylint:disable=unused-argument _sys.setprofile(_get_thread_profile()) _sys.settrace(_get_thread_trace()) def _after_run_task(self, func, args, kwargs, thread_result, _sys=sys): # pylint:disable=unused-argument _sys.setprofile(None) _sys.settrace(None) def __run_task(self, func, args, kwargs, thread_result): self._before_run_task(func, args, kwargs, thread_result) try: > thread_result.set(func(*args, **kwargs)) E socket.gaierror: [Errno -3] Temporary failure in name resolution /usr/lib/python3/dist-packages/gevent/threadpool.py:173: gaierror During handling of the above exception, another exception occurred: self = method = 'GET', url = '/locustio/locust/master/examples/basic.py', body = None headers = {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate, br', 'Accept': '*/*', 'Connection': 'keep-alive'} retries = Retry(total=0, connect=None, read=False, redirect=None, status=None) redirect = False, assert_same_host = False timeout = Timeout(connect=None, read=None, total=None), pool_timeout = None release_conn = False, chunked = False, body_pos = None response_kw = {'decode_content': False, 'preload_content': False} parsed_url = Url(scheme=None, auth=None, host=None, port=None, path='/locustio/locust/master/examples/basic.py', query=None, fragment=None) destination_scheme = None, conn = None, release_this_conn = True http_tunnel_required = False, err = None, clean_exit = False def urlopen( self, method, url, body=None, headers=None, retries=None, redirect=True, assert_same_host=True, timeout=_Default, pool_timeout=None, release_conn=None, chunked=False, body_pos=None, **response_kw ): """ Get a connection from the pool and perform an HTTP request. This is the lowest level call for making a request, so you'll need to specify all the raw details. .. note:: More commonly, it's appropriate to use a convenience method provided by :class:`.RequestMethods`, such as :meth:`request`. .. note:: `release_conn` will only behave as expected if `preload_content=False` because we want to make `preload_content=False` the default behaviour someday soon without breaking backwards compatibility. :param method: HTTP request method (such as GET, POST, PUT, etc.) :param url: The URL to perform the request on. :param body: Data to send in the request body, either :class:`str`, :class:`bytes`, an iterable of :class:`str`/:class:`bytes`, or a file-like object. :param headers: Dictionary of custom headers to send, such as User-Agent, If-None-Match, etc. If None, pool headers are used. If provided, these headers completely replace any pool-specific headers. :param retries: Configure the number of retries to allow before raising a :class:`~urllib3.exceptions.MaxRetryError` exception. Pass ``None`` to retry until you receive a response. Pass a :class:`~urllib3.util.retry.Retry` object for fine-grained control over different types of retries. Pass an integer number to retry connection errors that many times, but no other types of errors. Pass zero to never retry. If ``False``, then retries are disabled and any exception is raised immediately. Also, instead of raising a MaxRetryError on redirects, the redirect response will be returned. :type retries: :class:`~urllib3.util.retry.Retry`, False, or an int. :param redirect: If True, automatically handle redirects (status codes 301, 302, 303, 307, 308). Each redirect counts as a retry. Disabling retries will disable redirect, too. :param assert_same_host: If ``True``, will make sure that the host of the pool requests is consistent else will raise HostChangedError. When ``False``, you can use the pool on an HTTP proxy and request foreign hosts. :param timeout: If specified, overrides the default timeout for this one request. It may be a float (in seconds) or an instance of :class:`urllib3.util.Timeout`. :param pool_timeout: If set and the pool is set to block=True, then this method will block for ``pool_timeout`` seconds and raise EmptyPoolError if no connection is available within the time period. :param release_conn: If False, then the urlopen call will not release the connection back into the pool once a response is received (but will release if you read the entire contents of the response such as when `preload_content=True`). This is useful if you're not preloading the response's content immediately. You will need to call ``r.release_conn()`` on the response ``r`` to return the connection back into the pool. If None, it takes the value of ``response_kw.get('preload_content', True)``. :param chunked: If True, urllib3 will send the body using chunked transfer encoding. Otherwise, urllib3 will send the body using the standard content-length form. Defaults to False. :param int body_pos: Position to seek to in file-like body in the event of a retry or redirect. Typically this won't need to be set because urllib3 will auto-populate the value when needed. :param \\**response_kw: Additional parameters are passed to :meth:`urllib3.response.HTTPResponse.from_httplib` """ parsed_url = parse_url(url) destination_scheme = parsed_url.scheme if headers is None: headers = self.headers if not isinstance(retries, Retry): retries = Retry.from_int(retries, redirect=redirect, default=self.retries) if release_conn is None: release_conn = response_kw.get("preload_content", True) # Check host if assert_same_host and not self.is_same_host(url): raise HostChangedError(self, url, retries) # Ensure that the URL we're connecting to is properly encoded if url.startswith("/"): url = six.ensure_str(_encode_target(url)) else: url = six.ensure_str(parsed_url.url) conn = None # Track whether `conn` needs to be released before # returning/raising/recursing. Update this variable if necessary, and # leave `release_conn` constant throughout the function. That way, if # the function recurses, the original value of `release_conn` will be # passed down into the recursive call, and its value will be respected. # # See issue #651 [1] for details. # # [1] release_this_conn = release_conn http_tunnel_required = connection_requires_http_tunnel( self.proxy, self.proxy_config, destination_scheme ) # Merge the proxy headers. Only done when not using HTTP CONNECT. We # have to copy the headers dict so we can safely change it without those # changes being reflected in anyone else's copy. if not http_tunnel_required: headers = headers.copy() headers.update(self.proxy_headers) # Must keep the exception bound to a separate variable or else Python 3 # complains about UnboundLocalError. err = None # Keep track of whether we cleanly exited the except block. This # ensures we do proper cleanup in finally. clean_exit = False # Rewind body position, if needed. Record current position # for future rewinds in the event of a redirect/retry. body_pos = set_file_position(body, body_pos) try: # Request a connection from the queue. timeout_obj = self._get_timeout(timeout) conn = self._get_conn(timeout=pool_timeout) conn.timeout = timeout_obj.connect_timeout is_new_proxy_conn = self.proxy is not None and not getattr( conn, "sock", None ) if is_new_proxy_conn and http_tunnel_required: self._prepare_proxy(conn) # Make the request on the httplib connection object. > httplib_response = self._make_request( conn, method, url, timeout=timeout_obj, body=body, headers=headers, chunked=chunked, ) /usr/lib/python3/dist-packages/urllib3/connectionpool.py:716: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/connectionpool.py:405: in _make_request self._validate_conn(conn) /usr/lib/python3/dist-packages/urllib3/connectionpool.py:1059: in _validate_conn conn.connect() /usr/lib/python3/dist-packages/urllib3/connection.py:363: in connect self.sock = conn = self._new_conn() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def _new_conn(self): """Establish a socket connection and set nodelay settings on it. :return: New socket connection. """ extra_kw = {} if self.source_address: extra_kw["source_address"] = self.source_address if self.socket_options: extra_kw["socket_options"] = self.socket_options try: conn = connection.create_connection( (self._dns_host, self.port), self.timeout, **extra_kw ) except SocketTimeout: raise ConnectTimeoutError( self, "Connection to %s timed out. (connect timeout=%s)" % (self.host, self.timeout), ) except SocketError as e: > raise NewConnectionError( self, "Failed to establish a new connection: %s" % e ) E urllib3.exceptions.NewConnectionError: : Failed to establish a new connection: [Errno -3] Temporary failure in name resolution /usr/lib/python3/dist-packages/urllib3/connection.py:186: NewConnectionError During handling of the above exception, another exception occurred: self = request = , stream = False timeout = Timeout(connect=None, read=None, total=None), verify = True cert = None, proxies = OrderedDict([('no', 'localhost')]) def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection(request.url, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: > resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) /usr/lib/python3/dist-packages/requests/adapters.py:486: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/urllib3/connectionpool.py:800: in urlopen retries = retries.increment( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = Retry(total=0, connect=None, read=False, redirect=None, status=None) method = 'GET', url = '/locustio/locust/master/examples/basic.py' response = None error = NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution') _pool = _stacktrace = def increment( self, method=None, url=None, response=None, error=None, _pool=None, _stacktrace=None, ): """Return a new Retry object with incremented retry counters. :param response: A response object, or None, if the server did not return a response. :type response: :class:`~urllib3.response.HTTPResponse` :param Exception error: An error encountered during the request, or None if the response was received successfully. :return: A new ``Retry`` object. """ if self.total is False and error: # Disabled, indicate to re-raise the error. raise six.reraise(type(error), error, _stacktrace) total = self.total if total is not None: total -= 1 connect = self.connect read = self.read redirect = self.redirect status_count = self.status other = self.other cause = "unknown" status = None redirect_location = None if error and self._is_connection_error(error): # Connect retry? if connect is False: raise six.reraise(type(error), error, _stacktrace) elif connect is not None: connect -= 1 elif error and self._is_read_error(error): # Read retry? if read is False or not self._is_method_retryable(method): raise six.reraise(type(error), error, _stacktrace) elif read is not None: read -= 1 elif error: # Other retry? if other is not None: other -= 1 elif response and response.get_redirect_location(): # Redirect retry? if redirect is not None: redirect -= 1 cause = "too many redirects" redirect_location = response.get_redirect_location() status = response.status else: # Incrementing because of a server error like a 500 in # status_forcelist and the given method is in the allowed_methods cause = ResponseError.GENERIC_ERROR if response and response.status: if status_count is not None: status_count -= 1 cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status) status = response.status history = self.history + ( RequestHistory(method, url, error, status, redirect_location), ) new_retry = self.new( total=total, connect=connect, read=read, redirect=redirect, status=status_count, other=other, history=history, ) if new_retry.is_exhausted(): > raise MaxRetryError(_pool, url, error or ResponseError(cause)) E urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) /usr/lib/python3/dist-packages/urllib3/util/retry.py:592: MaxRetryError During handling of the above exception, another exception occurred: url = 'https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py' def download_locustfile_from_url(url: str) -> str: try: > response = requests.get(url) locust/argument_parser.py:193: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/requests/api.py:73: in get return request("get", url, params=params, **kwargs) /usr/lib/python3/dist-packages/requests/api.py:59: in request return session.request(method=method, url=url, **kwargs) /usr/lib/python3/dist-packages/requests/sessions.py:589: in request resp = self.send(prep, **send_kwargs) /usr/lib/python3/dist-packages/requests/sessions.py:703: in send r = adapter.send(request, **kwargs) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = request = , stream = False timeout = Timeout(connect=None, read=None, total=None), verify = True cert = None, proxies = OrderedDict([('no', 'localhost')]) def send( self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None ): """Sends PreparedRequest object. Returns Response object. :param request: The :class:`PreparedRequest ` being sent. :param stream: (optional) Whether to stream the request content. :param timeout: (optional) How long to wait for the server to send data before giving up, as a float, or a :ref:`(connect timeout, read timeout) ` tuple. :type timeout: float or tuple or urllib3 Timeout object :param verify: (optional) Either a boolean, in which case it controls whether we verify the server's TLS certificate, or a string, in which case it must be a path to a CA bundle to use :param cert: (optional) Any user-provided SSL certificate to be trusted. :param proxies: (optional) The proxies dictionary to apply to the request. :rtype: requests.Response """ try: conn = self.get_connection(request.url, proxies) except LocationValueError as e: raise InvalidURL(e, request=request) self.cert_verify(conn, request.url, verify, cert) url = self.request_url(request, proxies) self.add_headers( request, stream=stream, timeout=timeout, verify=verify, cert=cert, proxies=proxies, ) chunked = not (request.body is None or "Content-Length" in request.headers) if isinstance(timeout, tuple): try: connect, read = timeout timeout = TimeoutSauce(connect=connect, read=read) except ValueError: raise ValueError( f"Invalid timeout {timeout}. Pass a (connect, read) timeout tuple, " f"or a single float to set both timeouts to the same value." ) elif isinstance(timeout, TimeoutSauce): pass else: timeout = TimeoutSauce(connect=timeout, read=timeout) try: resp = conn.urlopen( method=request.method, url=url, body=request.body, headers=request.headers, redirect=False, assert_same_host=False, preload_content=False, decode_content=False, retries=self.max_retries, timeout=timeout, chunked=chunked, ) except (ProtocolError, OSError) as err: raise ConnectionError(err, request=request) except MaxRetryError as e: if isinstance(e.reason, ConnectTimeoutError): # TODO: Remove this in 3.0.0: see #2811 if not isinstance(e.reason, NewConnectionError): raise ConnectTimeout(e, request=request) if isinstance(e.reason, ResponseError): raise RetryError(e, request=request) if isinstance(e.reason, _ProxyError): raise ProxyError(e, request=request) if isinstance(e.reason, _SSLError): # This branch is for urllib3 v1.22 and later. raise SSLError(e, request=request) > raise ConnectionError(e, request=request) E requests.exceptions.ConnectionError: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) /usr/lib/python3/dist-packages/requests/adapters.py:519: ConnectionError During handling of the above exception, another exception occurred: self = def test_locustfile_from_url(self): > locustfiles = parse_locustfile_option( args=[ "-f", "https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py", ] ) locust/test/test_load_locustfile.py:216: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/argument_parser.py:369: in parse_locustfile_option locustfile_as_list = [ locust/argument_parser.py:370: in download_locustfile_from_url(f) if is_url(f.strip()) else f.strip() for f in options.locustfile.split(",") _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ url = 'https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py' def download_locustfile_from_url(url: str) -> str: try: response = requests.get(url) # Check if response is valid python code ast.parse(response.text) except requests.exceptions.RequestException as e: sys.stderr.write(f"Failed to get locustfile from: {url}. Exception: {e}") > sys.exit(1) E SystemExit: 1 locust/argument_parser.py:198: SystemExit ----------------------------- Captured stderr call ----------------------------- Failed to get locustfile from: https://raw.githubusercontent.com/locustio/locust/master/examples/basic.py. Exception: HTTPSConnectionPool(host='raw.githubusercontent.com', port=443): Max retries exceeded with url: /locustio/locust/master/examples/basic.py (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -3] Temporary failure in name resolution')) _____________________ TestLoggingOptions.test_log_to_file ______________________ self = def test_log_to_file(self): with temporary_file( textwrap.dedent( """ import logging from locust import User, task, constant class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") logging.info("custom log message") """ ) ) as file_path: with temporary_file("", suffix=".log") as log_file_path: try: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", "--logfile", log_file_path, ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:158: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp_5dzgeje_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________________ TestLoggingOptions.test_logging_output ____________________ self = def test_logging_output(self): with temporary_file( textwrap.dedent( """ import logging from locust import User, task, constant custom_logger = logging.getLogger("custom_logger") class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") logging.info("custom log message") custom_logger.info("test") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:58: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp5naagwdo_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________________ TestLoggingOptions.test_skip_logging _____________________ self = def test_skip_logging(self): with temporary_file( textwrap.dedent( """ from locust import User, task, constant class MyUser(User): wait_time = constant(2) @task def my_task(self): print("running my_task") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-u", "1", "-r", "1", "-t", "1", "--headless", "--skip-log-setup", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:117: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp_vfi9rv4_locustfile.py', '-u', '1', '-r', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ TestLoggingOptions.test_user_broken_on_start _________________ self = def test_user_broken_on_start(self): with temporary_file( textwrap.dedent( """ from locust import HttpUser, task class TestUser(HttpUser): host = "invalidhost" def on_start(self): self.client.get("/") """ ) ) as file_path: > output = subprocess.check_output( [ "locust", "-f", file_path, "-t", "1", "--headless", ], stderr=subprocess.STDOUT, timeout=10, text=True, ) locust/test/test_log.py:223: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp7u2ycc0s_locustfile.py', '-t', '1', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_autostart_multiple_locustfiles_with_shape ___ self = def test_autostart_multiple_locustfiles_with_shape(self): port = get_free_tcp_port() content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( [ "locust", "-f", f"{mocked1.file_path},{mocked2}", "--legacy-ui", "--web-port", str(port), "--autostart", "--autoquit", "3", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:794: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994303_3569832_50498.py,/tmp/tmp1te2hzv0_locustfile.py', '--legacy-ui', '--web-port', '36651', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________ StandaloneIntegrationTests.test_autostart_w_load_shape ____________ self = def test_autostart_w_load_shape(self): port = get_free_tcp_port() with mock_locustfile( content=MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) ) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--legacy-ui", "--web-port", str(port), "--autostart", "--autoquit", "3", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:727: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994303_5341413_6706.py', '--legacy-ui', '--web-port', '41111', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________ StandaloneIntegrationTests.test_autostart_w_run_time _____________ self = @unittest.skipIf(sys.platform == "darwin", reason="This is too messy on macOS") def test_autostart_w_run_time(self): port = get_free_tcp_port() with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--web-port", str(port), "-t", "3", "--autostart", "--autoquit", "1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:635: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994303_7173276_6284.py', '--web-port', '59117', '-t', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________ StandaloneIntegrationTests.test_autostart_wo_run_time _____________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_autostart_wo_run_time(self): port = get_free_tcp_port() with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--web-port", str(port), "--autostart", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:600: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994303_9114816_74093.py', '--web-port', '60911', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________ StandaloneIntegrationTests.test_command_line_user_selection __________ self = def test_command_line_user_selection(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): print("User1 is running") class User2(User): wait_time = constant(1) @task def t(self): print("User2 is running") class User3(User): wait_time = constant(1) @task def t(self): print("User3 is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "2s", "-u", "5", "-r", "10", "User2", "User3", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] self.assertNotIn("User1 is running", output) > self.assertIn("User2 is running", output) E AssertionError: 'User2 is running' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1080: AssertionError _______________ StandaloneIntegrationTests.test_custom_arguments _______________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_arguments(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.init_command_line_parser.add_listener def _(parser, **kw): parser.add_argument("--custom-string-arg") class TestUser(User): wait_time = constant(10) @task def my_task(self): print(self.environment.parsed_options.custom_string_arg) """ ) ) as file_path: # print(subprocess.check_output(["cat", file_path])) > proc = subprocess.Popen( ["locust", "-f", file_path, "--custom-string-arg", "command_line_value", "--web-port", str(port)], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:104: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp6eya88z7_locustfile.py', '--custom-string-arg', 'command_line_value', '--web-port', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________ StandaloneIntegrationTests.test_custom_arguments_in_file ___________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_arguments_in_file(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.init_command_line_parser.add_listener def _(parser, **kw): parser.add_argument("--custom-string-arg") class TestUser(User): wait_time = constant(10) @task def my_task(self): print(self.environment.parsed_options.custom_string_arg) """ ) ) as file_path: try: with open("locust.conf", "w") as conf_file: conf_file.write("custom-string-arg config_file_value") > proc = subprocess.Popen( ["locust", "-f", file_path, "--autostart"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:147: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmplk29ytrn_locustfile.py', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ StandaloneIntegrationTests.test_custom_exit_code _______________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_custom_exit_code(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events @events.quitting.add_listener def _(environment, **kw): environment.process_exit_code = 42 @events.quit.add_listener def _(exit_code, **kw): print(f"Exit code in quit event {exit_code}") class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:182: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpb3iocv7a_locustfile.py'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 80, errread = 81 errwrite = 82, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_default_headless_spawn_options ________ self = def test_default_headless_spawn_options(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--run-time", "1s", "--headless", "--loglevel", "DEBUG", "--exit-code-on-error", "0", # just to test --stop-timeout argument parsing, doesnt actually validate its function: "--stop-timeout", "1s", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:371: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994304_9551885_9237.py', '--host', 'https://test.com/', '--run-time', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_default_headless_spawn_options_with_shape ___ self = @unittest.skipIf(sys.version_info < (3, 9), reason="dies in 3.8 on GH and I cant be bothered to investigate it") def test_default_headless_spawn_options_with_shape(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:500: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994305_1496005_63489.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_error_when_duplicate_shape_class_names ____ self = def test_error_when_duplicate_shape_class_names(self): MOCK_LOCUSTFILE_CONTENT_C = MOCK_LOCUSTFILE_CONTENT_A + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) MOCK_LOCUSTFILE_CONTENT_D = MOCK_LOCUSTFILE_CONTENT_B + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None """ ) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_D) as file2: > proc = subprocess.Popen(["locust", "-f", f"{file1},{file2}"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1209: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp3c538t_q_locustfile.py,/tmp/tmphcwkd5qn_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_error_when_duplicate_userclass_names _____ self = def test_error_when_duplicate_userclass_names(self): MOCK_LOCUSTFILE_CONTENT_C = textwrap.dedent( """ from locust import User, task, constant, events class TestUser1(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file2: > proc = subprocess.Popen(["locust", "-f", f"{file1},{file2}"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1157: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmphugpgcmu_locustfile.py,/tmp/tmpq3dhdohb_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_error_when_locustfiles_directory_is_empty ___ self = def test_error_when_locustfiles_directory_is_empty(self): with TemporaryDirectory() as temp_dir: > proc = subprocess.Popen(["locust", "-f", temp_dir], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:1298: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmphjc5lts2'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 80, errread = 81 errwrite = 82, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_error_when_no_tasks_match_tags ________ self = def test_error_when_no_tasks_match_tags(self): content = """ from locust import HttpUser, TaskSet, task, constant, LoadTestShape, tag class MyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = constant(1) @tag("tag1") @task def task1(self): print("task1") """ with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "-t", "1", "--tags", "tag2", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1317: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994306_1612267_57454.py', '--headless', '-t', '1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_error_when_providing_both_run_time_and_a_shape_class _ self = def test_error_when_providing_both_run_time_and_a_shape_class(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "-f", mocked.file_path, "--run-time=1s", "--headless", "--exit-code-on-error", "0", ] ) locust/test/test_main.py:1226: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994306_3342395_92537.py', '--run-time=1s', '--headless', '--exit-code-on-error', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_graceful_exit_when_keyboard_interrupt _____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_graceful_exit_when_keyboard_interrupt(self): with temporary_file( content=textwrap.dedent( """ from locust import User, events, task, constant, LoadTestShape @events.test_stop.add_listener def on_test_stop(environment, **kwargs) -> None: print("Test Stopped") class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked, "--headless", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1363: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp2qt31989_locustfile.py', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______ StandaloneIntegrationTests.test_headless_spawn_options_wo_run_time ______ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_headless_spawn_options_wo_run_time(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:421: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994306_7985282_89856.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = 81, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________________ StandaloneIntegrationTests.test_help_arg ___________________ self = def test_help_arg(self): > output = subprocess.check_output( ["locust", "--help"], stderr=subprocess.STDOUT, timeout=5, text=True, ).strip() locust/test/test_main.py:72: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , args = ['locust', '--help'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______________ StandaloneIntegrationTests.test_html_report_option ______________ self = def test_html_report_option(self): with mock_locustfile() as mocked: with temporary_file("", suffix=".html") as html_report_file_path: try: > output = subprocess.check_output( [ "locust", "-f", mocked.file_path, "--legacy-ui", "--host", "https://test.com/", "--run-time", "2s", "--headless", "--exit-code-on-error", "0", "--html", html_report_file_path, ], stderr=subprocess.STDOUT, timeout=10, text=True, ).strip() locust/test/test_main.py:1088: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:404: in check_output with Popen(*popenargs, stdout=PIPE, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994307_2475893_51474.py', '--legacy-ui', '--host', 'https://test.com/', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 80, errread = -1, errwrite = 80, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____________________ StandaloneIntegrationTests.test_input _____________________ self = @unittest.skipIf(os.name == "nt", reason="termios doesnt exist on windows, and thus we cannot import pty") def test_input(self): import pty LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, TaskSet, task, between class UserSubclass(User): wait_time = between(0.2, 0.8) @task def t(self): print("Test task is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: stdin_m, stdin_s = pty.openpty() stdin = os.fdopen(stdin_m, "wb", 0) proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "7s", "-u", "0", "--loglevel", "INFO", ] ), stderr=STDOUT, stdin=stdin_s, stdout=PIPE, shell=True, text=True, ) gevent.sleep(1) stdin.write(b"w") gevent.sleep(1) stdin.write(b"W") gevent.sleep(1) stdin.write(b"s") gevent.sleep(1) stdin.write(b"S") gevent.sleep(1) # This should not do anything since we are already at zero users stdin.write(b"S") gevent.sleep(1) output = proc.communicate()[0] stdin.close() > self.assertIn("Ramping to 1 users at a rate of 100.00 per second", output) E AssertionError: 'Ramping to 1 users at a rate of 100.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:922: AssertionError _________ StandaloneIntegrationTests.test_invalid_percentile_parameter _________ self = def test_invalid_percentile_parameter(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_CHART PERCENTILES_TO_CHART[0] = 1.2 class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path, "--autostart"], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:287: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpc_3xtjqy_locustfile.py', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________ StandaloneIntegrationTests.test_invalid_stop_timeout_string __________ self = def test_invalid_stop_timeout_string(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "https://test.com/", "--stop-timeout", "asdf1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:400: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994313_804437_70490.py', '--host', 'https://test.com/', '--stop-timeout', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_no_error_when_same_userclass_in_two_files ___ self = def test_no_error_when_same_userclass_in_two_files(self): with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: MOCK_LOCUSTFILE_CONTENT_C = textwrap.dedent( f""" from {os.path.basename(file1)[:-3]} import TestUser1 """ ) print(MOCK_LOCUSTFILE_CONTENT_C) with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_C) as file2: > proc = subprocess.Popen( ["locust", "-f", f"{file1},{file2}", "-t", "1", "--headless"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:1173: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp3sj99siu_locustfile.py,/tmp/tmpx90gy9bd_locustfile.py', '-t', '1', '--headless'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ----------------------------- Captured stdout call ----------------------------- from tmp3sj99siu_locustfile import TestUser1 _____________ StandaloneIntegrationTests.test_percentile_parameter _____________ self = def test_percentile_parameter(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_CHART PERCENTILES_TO_CHART[0] = 0.9 PERCENTILES_TO_CHART[1] = 0.4 class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen( ["locust", "-f", file_path, "--web-port", str(port), "--autostart"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:233: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmppbx_nj2l_locustfile.py', '--web-port', '43839', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ StandaloneIntegrationTests.test_percentiles_to_statistics ___________ self = def test_percentiles_to_statistics(self): port = get_free_tcp_port() with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events from locust.stats import PERCENTILES_TO_STATISTICS PERCENTILES_TO_STATISTICS = [0.9, 0.99] class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen( ["locust", "-f", file_path, "--web-port", str(port), "--autostart"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:259: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp3aekvlym_locustfile.py', '--web-port', '50433', '--autostart'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___ StandaloneIntegrationTests.test_run_autostart_with_multiple_locustfiles ____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_run_autostart_with_multiple_locustfiles(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(dir=temp_dir): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(1) @task def my_task(self): print("running my_task()") """ ), dir=temp_dir, ): > proc = subprocess.Popen( [ "locust", "-f", temp_dir, "--autostart", "-u", "2", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:685: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmpl8f10zta', '--autostart', '-u', '2', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ____ StandaloneIntegrationTests.test_run_headless_with_multiple_locustfiles ____ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_run_headless_with_multiple_locustfiles(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(dir=temp_dir): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(1) @task def my_task(self): print("running my_task()") """ ), dir=temp_dir, ): > proc = subprocess.Popen( [ "locust", "-f", temp_dir, "--headless", "-u", "2", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:461: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp43z7nsda', '--headless', '-u', '2', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_run_headless_with_multiple_locustfiles_with_shape _ self = def test_run_headless_with_multiple_locustfiles_with_shape(self): content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( [ "locust", "-f", f"{mocked1.file_path},{mocked2}", "--host", "https://test.com/", "--headless", "--exit-code-on-error", "0", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:565: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994315_0601404_67926.py,/tmp/tmpf4v_qv2w_locustfile.py', '--host', 'https://test.com/', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ StandaloneIntegrationTests.test_run_with_userclass_picker ___________ self = def test_run_with_userclass_picker(self): with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_A) as file1: with temporary_file(content=MOCK_LOCUSTFILE_CONTENT_B) as file2: > proc = subprocess.Popen( ["locust", "-f", f"{file1},{file2}", "--class-picker"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1130: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp3vwaylaj_locustfile.py,/tmp/tmpgy8xsyv4_locustfile.py', '--class-picker'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_shape_class_log_disabled_parameters ______ self = def test_shape_class_log_disabled_parameters(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "--headless", "-f", mocked.file_path, "--exit-code-on-error=0", "--users=1", "--spawn-rate=1", ] ) locust/test/test_main.py:1252: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '--headless', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994315_4979556_21484.py', '--exit-code-on-error=0', '--users=1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ StandaloneIntegrationTests.test_shape_class_with_use_common_options ______ self = def test_shape_class_with_use_common_options(self): content = MOCK_LOCUSTFILE_CONTENT + textwrap.dedent( """ from locust import LoadTestShape class TestShape(LoadTestShape): use_common_options = True def tick(self): return None """ ) with mock_locustfile(content=content) as mocked: > out = self.assert_run( [ "locust", "-f", mocked.file_path, "--run-time=1s", "--users=1", "--spawn-rate=1", "--headless", "--exit-code-on-error=0", ] ) locust/test/test_main.py:1280: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/test/test_main.py:65: in assert_run out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout) /usr/lib/python3/dist-packages/gevent/subprocess.py:1977: in run with Popen(*popenargs, **kwargs) as process: /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994315_6983454_38463.py', '--run-time=1s', '--users=1', '--spawn-rate=1', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___ StandaloneIntegrationTests.test_spawing_with_fixed_multiple_locustfiles ____ self = def test_spawing_with_fixed_multiple_locustfiles(self): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A) as mocked1: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B) as mocked2: proc = subprocess.Popen( " ".join( [ "locust", "-f", f"{mocked1.file_path},{mocked2.file_path}", "--headless", "--run-time", "5s", "-u", "10", "-r", "10", "--loglevel", "INFO", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] > self.assertIn("Ramping to 10 users at a rate of 10.00 per second", output) E AssertionError: 'Ramping to 10 users at a rate of 10.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1022: AssertionError _____________ StandaloneIntegrationTests.test_spawning_with_fixed ______________ self = def test_spawning_with_fixed(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): fixed_count = 2 wait_time = constant(1) @task def t(self): print("Test task is running") class User2(User): wait_time = constant(1) @task def t(self): print("Test task is running") class User3(User): wait_time = constant(1) @task def t(self): print("Test task is running") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: proc = subprocess.Popen( " ".join( [ "locust", "-f", mocked.file_path, "--headless", "--run-time", "5s", "-u", "10", "-r", "10", "--loglevel", "INFO", ] ), stderr=STDOUT, stdout=PIPE, shell=True, text=True, ) output = proc.communicate()[0] > self.assertIn("Ramping to 10 users at a rate of 10.00 per second", output) E AssertionError: 'Ramping to 10 users at a rate of 10.00 per second' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:987: AssertionError _________________ StandaloneIntegrationTests.test_web_options __________________ self = @unittest.skipIf(platform.system() == "Darwin", reason="Messy on macOS on GH") @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_web_options(self): port = get_free_tcp_port() if platform.system() != "Darwin": # MacOS only sets up the loopback interface for 127.0.0.1 and not for 127.*.*.*, so we cant test this with mock_locustfile() as mocked: > proc = subprocess.Popen( ["locust", "-f", mocked.file_path, "--web-host", "127.0.0.2", "--web-port", str(port)], stdout=PIPE, stderr=PIPE, ) locust/test/test_main.py:838: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994316_1415002_73102.py', '--web-host', '127.0.0.2', '--web-port', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________________ StandaloneIntegrationTests.test_webserver ___________________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver(self): with temporary_file( content=textwrap.dedent( """ from locust import User, task, constant, events class TestUser(User): wait_time = constant(3) @task def my_task(self): print("running my_task()") """ ) ) as file_path: > proc = subprocess.Popen(["locust", "-f", file_path], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:206: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmppraqy9ya_locustfile.py'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = 82 errwrite = 83, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ StandaloneIntegrationTests.test_webserver_multiple_locustfiles ________ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles(self): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A) as mocked1: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B) as mocked2: > proc = subprocess.Popen( ["locust", "-f", f"{mocked1.file_path},{mocked2.file_path}"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:297: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994316_5451298_91199.py,/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994316_5453756_40084.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ StandaloneIntegrationTests.test_webserver_multiple_locustfiles_in_directory __ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles_in_directory(self): with TemporaryDirectory() as temp_dir: with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_A, dir=temp_dir): with mock_locustfile(content=MOCK_LOCUSTFILE_CONTENT_B, dir=temp_dir): > proc = subprocess.Popen(["locust", "-f", temp_dir], stdout=PIPE, stderr=PIPE, text=True) locust/test/test_main.py:314: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/tmp/tmp7c91awqi'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = 82 errwrite = 83, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ StandaloneIntegrationTests.test_webserver_multiple_locustfiles_with_shape ___ self = @unittest.skipIf(os.name == "nt", reason="Signal handling on windows is hard") def test_webserver_multiple_locustfiles_with_shape(self): content = textwrap.dedent( """ from locust import User, task, between class TestUser2(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task() again") """ ) with mock_locustfile(content=content) as mocked1: with temporary_file( content=textwrap.dedent( """ from locust import User, task, between, LoadTestShape class LoadTestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return (10, 1) return None class TestUser(User): wait_time = between(2, 4) @task def my_task(self): print("running my_task()") """ ) ) as mocked2: > proc = subprocess.Popen( ["locust", "-f", f"{mocked1.file_path},{mocked2}"], stdout=PIPE, stderr=PIPE, text=True ) locust/test/test_main.py:357: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994317_023946_96416.py,/tmp/tmpektl8l5c_locustfile.py'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ DistributedIntegrationTests.test_distributed _________________ self = def test_distributed(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-u", "3", "-t", "5s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1570: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994317_2254097_71068.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____________ DistributedIntegrationTests.test_distributed_events ______________ self = def test_distributed_events(self): content = ( MOCK_LOCUSTFILE_CONTENT + """ from locust import events from locust.runners import MasterRunner @events.test_start.add_listener def on_test_start(environment, **kwargs): if isinstance(environment.runner, MasterRunner): print("test_start on master") else: print("test_start on worker") @events.test_stop.add_listener def on_test_stop(environment, **kwargs): if isinstance(environment.runner, MasterRunner): print("test_stop on master") else: print("test_stop on worker") """ ) with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-t", "1", "--exit-code-on-error", "0", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1448: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994317_4090383_48071.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ DistributedIntegrationTests.test_distributed_report_timeout_expired ______ self = def test_distributed_report_timeout_expired(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.01" ) as _: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-u", "3", "-t", "5s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1624: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994317_59491_42288.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ______________ DistributedIntegrationTests.test_distributed_tags _______________ self = def test_distributed_tags(self): content = """ from locust import HttpUser, TaskSet, task, between, LoadTestShape, tag class SecondUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(0, 0.1) @tag("tag1") @task def task1(self): print("task1") @tag("tag2") @task def task2(self): print("task2") """ with mock_locustfile(content=content) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "1", "-t", "1", "-u", "2", "--exit-code-on-error", "0", "-L", "DEBUG", "--tags", "tag1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1509: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994317_8542354_99682.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ DistributedIntegrationTests.test_distributed_with_locustfile_distribution_not_plain_filename _ self = def test_distributed_with_locustfile_distribution_not_plain_filename(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path[:-3], # remove ".py" "--headless", "--master", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1804: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994318_0371792_61921', '--headless', '--master'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ DistributedIntegrationTests.test_expect_workers ________________ self = def test_expect_workers(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "--expect-workers-max-wait", "1", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1404: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994318_2254548_66838.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _________________ DistributedIntegrationTests.test_json_schema _________________ self = def test_json_schema(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import HttpUser, task, constant class QuickstartUser(HttpUser): wait_time = constant(1) @task def hello_world(self): self.client.get("/") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--host", "http://google.com", "--headless", "-u", "1", "-t", "2s", "--json", ], stderr=DEVNULL, stdout=PIPE, text=True, ) locust/test/test_main.py:1848: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994318_3972821_45222.py', '--host', 'http://google.com', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 82, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ___________ DistributedIntegrationTests.test_locustfile_distribution ___________ self = def test_locustfile_distribution(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): pass """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "-t", "1s", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1679: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994318_6529691_49293.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = -1, errwrite = 81, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _ DistributedIntegrationTests.test_locustfile_distribution_with_workers_started_first _ self = def test_locustfile_distribution_with_workers_started_first(self): LOCUSTFILE_CONTENT = textwrap.dedent( """ from locust import User, task, constant class User1(User): wait_time = constant(1) @task def t(self): print("hello") """ ) with mock_locustfile(content=LOCUSTFILE_CONTENT) as mocked: > proc_worker = subprocess.Popen( [ "locust", "-f", "-", "--worker", ], stderr=STDOUT, stdout=PIPE, text=True, ) locust/test/test_main.py:1751: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '-', '--worker'], executable = 'locust' preexec_fn = None, close_fds = True, pass_fds = (), cwd = None, env = None universal_newlines = None, startupinfo = None, creationflags = 0, shell = False p2cread = -1, p2cwrite = -1, c2pread = 11, c2pwrite = 81, errread = -1 errwrite = 81, restore_signals = True, gid = None, gids = None, uid = None umask = -1, start_new_session = False, process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________________ DistributedIntegrationTests.test_processes __________________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes(self): with mock_locustfile() as mocked: command = f"locust -f {mocked.file_path} --processes 4 --headless --run-time 1 --exit-code-on-error 0" proc = subprocess.Popen( command, shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, stderr = proc.communicate(timeout=9) except Exception: proc.kill() assert False, f"locust process never finished: {command}" self.assertNotIn("Traceback", stderr) > self.assertIn("(index 3) reported as ready", stderr) E AssertionError: '(index 3) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:1993: AssertionError ____________ DistributedIntegrationTests.test_processes_autodetect _____________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_autodetect(self): with mock_locustfile() as mocked: command = f"locust -f {mocked.file_path} --processes -1 --headless --run-time 1 --exit-code-on-error 0" proc = subprocess.Popen( command, shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, stderr = proc.communicate(timeout=9) except Exception: proc.kill() assert False, f"locust process never finished: {command}" self.assertNotIn("Traceback", stderr) > self.assertIn("(index 0) reported as ready", stderr) E AssertionError: '(index 0) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:2013: AssertionError ______________ DistributedIntegrationTests.test_processes_ctrl_c _______________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_ctrl_c(self): with mock_locustfile() as mocked: > proc = psutil.Popen( # use psutil.Popen instead of subprocess.Popen to use extra features [ "locust", "-f", mocked.file_path, "--processes", "4", "--headless", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2064: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/psutil/__init__.py:1378: in __init__ self.__subproc = subprocess.Popen(*args, **kwargs) /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994319_3690515_96580.py', '--processes', '4', '--headless', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __ DistributedIntegrationTests.test_processes_error_doesnt_blow_up_completely __ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_error_doesnt_blow_up_completely(self): with mock_locustfile() as mocked: > proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--processes", "4", "-L", "DEBUG", "UserThatDoesntExist", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994319_6526463_70422.py', '--processes', '4', '-L', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError __________ DistributedIntegrationTests.test_processes_separate_worker __________ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_processes_separate_worker(self): with mock_locustfile() as mocked: master_proc = subprocess.Popen( f"locust -f {mocked.file_path} --master --headless --run-time 1 --exit-code-on-error 0 --expect-workers-max-wait 2", shell=True, stdout=PIPE, stderr=PIPE, text=True, ) worker_parent_proc = subprocess.Popen( f"locust -f {mocked.file_path} --processes 4 --worker", shell=True, stdout=PIPE, stderr=PIPE, text=True, ) try: _, worker_stderr = worker_parent_proc.communicate(timeout=9) except Exception: master_proc.kill() worker_parent_proc.kill() _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() assert False, f"worker never finished: {worker_stderr}" try: _, master_stderr = master_proc.communicate(timeout=9) except Exception: master_proc.kill() worker_parent_proc.kill() _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() assert False, f"master never finished: {master_stderr}" _, worker_stderr = worker_parent_proc.communicate() _, master_stderr = master_proc.communicate() self.assertNotIn("Traceback", worker_stderr) self.assertNotIn("Traceback", master_stderr) self.assertNotIn("Gave up waiting for workers to connect", master_stderr) > self.assertIn("(index 3) reported as ready", master_stderr) E AssertionError: '(index 3) reported as ready' not found in '/build/reproducible-path/locust-2.24.0/debian/locust: line 2: from: command not found\n/build/reproducible-path/locust-2.24.0/debian/locust: line 5: syntax error: unexpected end of file\n' locust/test/test_main.py:2058: AssertionError ______ DistributedIntegrationTests.test_processes_workers_quit_unexpected ______ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") @unittest.skipIf(sys.platform == "darwin", reason="Flaky on macOS :-/") def test_processes_workers_quit_unexpected(self): content = """ from locust import runners, events, User, task import sys runners.HEARTBEAT_INTERVAL = 0.1 @events.test_start.add_listener def on_test_start(environment, **_kwargs): if isinstance(environment.runner, runners.WorkerRunner): sys.exit(42) class AnyUser(User): @task def mytask(self): pass """ with mock_locustfile(content=content) as mocked: > worker_proc = subprocess.Popen( ["locust", "-f", mocked.file_path, "--processes", "2", "--worker"], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2202: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994319_9815176_64828.py', '--processes', '2', '--worker'] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _______________ DistributedIntegrationTests.test_worker_indexes ________________ self = def test_worker_indexes(self): content = """ from locust import HttpUser, task, between class AnyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = between(0, 0.1) @task def my_task(self): print("worker index:", self.environment.runner.worker_index) """ with mock_locustfile(content=content) as mocked: > master = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--headless", "--master", "--expect-workers", "2", "-t", "5", "-u", "2", "-L", "DEBUG", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:1900: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994320_2252839_76703.py', '--headless', '--master', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError _____ DistributedIntegrationTests.test_workers_shut_down_if_master_is_gone _____ self = @unittest.skipIf(os.name == "nt", reason="--processes doesnt work on windows") def test_workers_shut_down_if_master_is_gone(self): content = """ from locust import HttpUser, task, constant, runners runners.MASTER_HEARTBEAT_TIMEOUT = 2 class AnyUser(HttpUser): host = "http://127.0.0.1:8089" wait_time = constant(1) @task def my_task(self): print("worker index:", self.environment.runner.worker_index) """ with mock_locustfile(content=content) as mocked: > master_proc = subprocess.Popen( [ "locust", "-f", mocked.file_path, "--master", "--headless", "--expect-workers", "2", ], stdout=PIPE, stderr=PIPE, text=True, ) locust/test/test_main.py:2115: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib/python3/dist-packages/gevent/subprocess.py:807: in __init__ self._execute_child(args, executable, preexec_fn, close_fds, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = args = ['locust', '-f', '/build/reproducible-path/locust-2.24.0/locust/test/mock_locustfile_1710994320_4573784_57696.py', '--master', '--headless', '--expect-workers', ...] executable = 'locust', preexec_fn = None, close_fds = True, pass_fds = () cwd = None, env = None, universal_newlines = None, startupinfo = None creationflags = 0, shell = False, p2cread = -1, p2cwrite = -1, c2pread = 11 c2pwrite = 81, errread = 82, errwrite = 83, restore_signals = True, gid = None gids = None, uid = None, umask = -1, start_new_session = False process_group = None def _execute_child(self, args, executable, preexec_fn, close_fds, pass_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite, restore_signals, gid, gids, uid, umask, start_new_session, process_group): """Execute program (POSIX version)""" if isinstance(args, (str, bytes)): args = [args] elif isinstance(args, PathLike): if shell: raise TypeError('path-like args is not allowed when ' 'shell is true') args = [fsencode(args)] # os.PathLike -> [str] else: args = list(args) if shell: # On Android the default shell is at '/system/bin/sh'. unix_shell = ( '/system/bin/sh' if hasattr(sys, 'getandroidapilevel') else '/bin/sh' ) args = [unix_shell, "-c"] + args if executable: args[0] = executable if executable is None: executable = args[0] self._loop.install_sigchld() # For transferring possible exec failure from child to parent # The first char specifies the exception type: 0 means # OSError, 1 means some other error. errpipe_read, errpipe_write = self.pipe_cloexec() # errpipe_write must not be in the standard io 0, 1, or 2 fd range. low_fds_to_close = [] while errpipe_write < 3: low_fds_to_close.append(errpipe_write) errpipe_write = os.dup(errpipe_write) for low_fd in low_fds_to_close: os.close(low_fd) try: try: gc_was_enabled = gc.isenabled() # Disable gc to avoid bug where gc -> file_dealloc -> # write to stderr -> hang. http://bugs.python.org/issue1336 gc.disable() try: self.pid = fork_and_watch(self._on_child, self._loop, True, fork) except: if gc_was_enabled: gc.enable() raise if self.pid == 0: # Child # XXX: Technically we're doing a lot of stuff here that # may not be safe to do before a exec(), depending on the OS. # CPython 3 goes to great lengths to precompute a lot # of this info before the fork and pass it all to C functions that # try hard not to call things like malloc(). (Of course, # CPython 2 pretty much did what we're doing.) try: # Close parent's pipe ends if p2cwrite != -1: os.close(p2cwrite) if c2pread != -1: os.close(c2pread) if errread != -1: os.close(errread) os.close(errpipe_read) # When duping fds, if there arises a situation # where one of the fds is either 0, 1 or 2, it # is possible that it is overwritten (#12607). if c2pwrite == 0: c2pwrite = os.dup(c2pwrite) _set_inheritable(c2pwrite, False) while errwrite in (0, 1): errwrite = os.dup(errwrite) _set_inheritable(errwrite, False) # Dup fds for child def _dup2(existing, desired): # dup2() removes the CLOEXEC flag but # we must do it ourselves if dup2() # would be a no-op (issue #10806). if existing == desired: self._set_cloexec_flag(existing, False) elif existing != -1: os.dup2(existing, desired) try: self._remove_nonblock_flag(desired) except OSError: # Ignore EBADF, it may not actually be # open yet. # Tested beginning in 3.7.0b3 test_subprocess.py pass _dup2(p2cread, 0) _dup2(c2pwrite, 1) _dup2(errwrite, 2) # Close pipe fds. Make sure we don't close the # same fd more than once, or standard fds. if not True: closed = set([None]) for fd in (p2cread, c2pwrite, errwrite): if fd not in closed and fd > 2: os.close(fd) closed.add(fd) # Python 3 (with a working set_inheritable): # We no longer manually close p2cread, # c2pwrite, and errwrite here as # _close_open_fds takes care when it is # not already non-inheritable. if cwd is not None: try: os.chdir(cwd) except OSError as e: e._failed_chdir = True raise # Python 3.9 if umask >= 0: os.umask(umask) # XXX: CPython does _Py_RestoreSignals here. # Then setsid() based on ??? if gids: os.setgroups(gids) if gid: os.setregid(gid, gid) if uid: os.setreuid(uid, uid) if process_group is not None: os.setpgid(0, process_group) if preexec_fn: preexec_fn() # Close all other fds, if asked for. This must be done # after preexec_fn runs. if close_fds: fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) self._close_fds(fds_to_keep, errpipe_write) if restore_signals: # restore the documented signals back to sig_dfl; # not all will be defined on every platform for sig in 'SIGPIPE', 'SIGXFZ', 'SIGXFSZ': sig = getattr(signal, sig, None) if sig is not None: signal.signal(sig, signal.SIG_DFL) if start_new_session: os.setsid() if env is None: os.execvp(executable, args) else: # Python 3.6 started testing for # bytes values in the env; it also # started encoding strs using # fsencode and using a lower-level # API that takes a list of keys # and values. We don't have access # to that API, so we go the reverse direction. env = {os.fsdecode(k) if isinstance(k, bytes) else k: os.fsdecode(v) if isinstance(v, bytes) else v for k, v in env.items()} os.execvpe(executable, args, env) except: exc_type, exc_value, tb = sys.exc_info() # Save the traceback and attach it to the exception object exc_lines = traceback.format_exception(exc_type, exc_value, tb) exc_value.child_traceback = ''.join(exc_lines) os.write(errpipe_write, pickle.dumps(exc_value)) finally: # Make sure that the process exits no matter what. # The return code does not matter much as it won't be # reported to the application os._exit(1) # Parent self._child_created = True if gc_was_enabled: gc.enable() finally: # be sure the FD is closed no matter what os.close(errpipe_write) # self._devnull is not always defined. devnull_fd = getattr(self, '_devnull', None) if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd: os.close(p2cread) if c2pwrite != -1 and c2pread != -1 and c2pwrite != devnull_fd: os.close(c2pwrite) if errwrite != -1 and errread != -1 and errwrite != devnull_fd: os.close(errwrite) if devnull_fd is not None: os.close(devnull_fd) # Prevent a double close of these fds from __init__ on error. self._closed_child_pipe_fds = True # Wait for exec to fail or succeed; possibly raising exception errpipe_read = FileObject(errpipe_read, 'rb') data = errpipe_read.read() finally: try: if hasattr(errpipe_read, 'close'): errpipe_read.close() else: os.close(errpipe_read) except OSError: # Especially on PyPy, we sometimes see the above # `os.close(errpipe_read)` raise an OSError. # It's not entirely clear why, but it happens in # InterprocessSignalTests.test_main sometimes, which must mean # we have some sort of race condition. pass finally: errpipe_read = -1 if data != b"": self.wait() child_exception = pickle.loads(data) for fd in (p2cwrite, c2pread, errread): if fd is not None and fd != -1: os.close(fd) if isinstance(child_exception, OSError): child_exception.filename = executable if hasattr(child_exception, '_failed_chdir'): child_exception.filename = cwd > raise child_exception E OSError: [Errno 8] Exec format error: 'locust' /usr/lib/python3/dist-packages/gevent/subprocess.py:1814: OSError ________ TestMasterRunner.test_attributes_populated_when_calling_start _________ self = def test_attributes_populated_when_calling_start(self): class MyUser1(User): @task def my_task(self): pass class MyUser2(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser1, MyUser2]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) master.start(7, 7) > self.assertEqual({"MyUser1": 4, "MyUser2": 3}, master.target_user_classes_count) E AssertionError: {'MyUser1': 4, 'MyUser2': 3} != {} E - {'MyUser1': 4, 'MyUser2': 3} E + {} locust/test/test_runners.py:3033: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ________________ TestMasterRunner.test_custom_shape_scale_down _________________ self = def test_custom_shape_scale_down(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return 5, 5 elif run_time < 4: return 1, 5 else: return None self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() sleep(0.5) # Wait for shape_worker to update user_count num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 5, num_users, "Total number of users in first stage of shape test is not 5: %i" % num_users ) E AssertionError: 5 != 0 : Total number of users in first stage of shape test is not 5: 0 locust/test/test_runners.py:2907: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 5 users at 5.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING root:runners.py:305 CPU usage above 90%! This may constrain your throughput and may even give inconsistent response time measurements! See https://docs.locust.io/en/stable/running-distributed.html for how to distribute the load over multiple CPU cores or machines ______________ TestMasterRunner.test_custom_shape_scale_interval _______________ self = def test_custom_shape_scale_interval(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def __init__(self): super().__init__() self._users_num = [1, 1, 1, 2, 2, 3, 3, 3, 4] self._index = 0 def tick(self): if self._index >= len(self._users_num): return None users_num = self._users_num[self._index] self._index += 1 return users_num, users_num self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() # Wait for shape_worker to update user_count sleep(0.5) num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 1, num_users, "Total number of users in first stage of shape test is not 1: %i" % num_users ) E AssertionError: 1 != 0 : Total number of users in first stage of shape test is not 1: 0 locust/test/test_runners.py:2800: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 1 users at 1.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _________________ TestMasterRunner.test_custom_shape_scale_up __________________ self = def test_custom_shape_scale_up(self): class MyUser(User): @task def my_task(self): pass class TestShape(LoadTestShape): def tick(self): run_time = self.get_run_time() if run_time < 2: return 1, 1 elif run_time < 4: return 2, 2 else: return None self.environment.shape_class = TestShape() with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[MyUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) # Start the shape_worker self.environment.shape_class.reset_time() master.start_shape() sleep(0.5) # Wait for shape_worker to update user_count num_users = sum( sum(msg.data["user_classes_count"].values()) for _, msg in server.outbox if msg.type != "ack" ) > self.assertEqual( 1, num_users, "Total number of users in first stage of shape test is not 1: %i" % num_users ) E AssertionError: 1 != 0 : Total number of users in first stage of shape test is not 1: 0 locust/test/test_runners.py:2858: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. INFO locust.runners:runners.py:329 Shape test starting. INFO locust.runners:runners.py:337 Shape worker starting INFO locust.runners:runners.py:356 Shape test updating to 1 users at 1.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _____________ TestMasterRunner.test_last_worker_missing_stops_test _____________ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=0.1) def test_last_worker_missing_stops_test(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) server.mocked_send(Message("client_ready", __version__, "fake_client3")) master.start(3, 3) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("spawning", None, "fake_client3")) sleep(0.2) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client1", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client2", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client3", ) ) sleep(0.2) self.assertEqual(0, len(master.clients.missing)) > self.assertEqual(3, master.worker_count) E AssertionError: 3 != 0 locust/test/test_runners.py:2236: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client3. Asking worker to quit. ____________ TestMasterRunner.test_last_worker_quitting_stops_test _____________ self = def test_last_worker_quitting_stops_test(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) master.start(1, 2) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("quit", None, "fake_client1")) sleep(0.1) > self.assertEqual(1, len(master.clients.all)) E AssertionError: 1 != 0 locust/test/test_runners.py:2183: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. ___________ TestMasterRunner.test_master_discard_first_client_ready ____________ self = def test_master_discard_first_client_ready(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: server.mocked_send(Message("client_ready", __version__, "dummy_client")) # discard first client_ready msg server.queue.get() master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "dummy_client")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3148: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (dummy_client). That's not going to work. _________ TestMasterRunner.test_master_marks_downed_workers_as_missing _________ self = def test_master_marks_downed_workers_as_missing(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(6) # print(master.clients['fake_client'].__dict__) > assert master.clients["fake_client"].state == STATE_MISSING locust/test/test_runners.py:2162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = , k = 'fake_client' def __getitem__(self, k: str) -> WorkerNode: > return self._worker_nodes[k] E KeyError: 'fake_client' locust/runners.py:636: KeyError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. INFO locust.runners:runners.py:356 Shape test updating to 2 users at 2.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:356 Shape test updating to 2 users at 2.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:342 Shape test stopping INFO locust.runners:runners.py:933 Worker 0 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 1 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 2 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 3 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:933 Worker 4 failed to send heartbeat, setting state to missing. INFO locust.runners:runners.py:941 The last worker went missing, stopping test. INFO locust.runners:runners.py:342 Shape test stopping INFO locust.runners:runners.py:356 Shape test updating to 3 users at 3.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected INFO locust.runners:runners.py:356 Shape test updating to 4 users at 4.00 spawn rate WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ________________ TestMasterRunner.test_master_reset_connection _________________ self = def test_master_reset_connection(self): """Test that connection will be reset when network issues found""" with mock.patch("locust.runners.FALLBACK_INTERVAL", new=0.1): with mock.patch("locust.rpc.rpc.Server", mocked_rpc(raise_on_close=False)) as server: master = self.get_runner() self.assertEqual(0, len(master.clients)) server.mocked_send(Message("client_ready", NETWORK_BROKEN, "fake_client")) self.assertTrue(master.connection_broken) server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(1) self.assertFalse(master.connection_broken) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2998: AssertionError ------------------------------ Captured log call ------------------------------- INFO locust.runners:runners.py:342 Shape test stopping ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. INFO locust.runners:runners.py:959 Resetting RPC server and all worker connections. ________ TestMasterRunner.test_rebalance_locust_users_on_worker_connect ________ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=600) def test_rebalance_locust_users_on_worker_connect(self): class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2511: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. ____________ TestMasterRunner.test_reset_connection_after_RPCError _____________ self = def test_reset_connection_after_RPCError(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc(raise_on_close=False)) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "fake_client")) sleep(0.2) self.assertFalse(master.connection_broken) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3007: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client). That's not going to work. ______________ TestMasterRunner.test_spawn_correct_worker_indexes ______________ self = def test_spawn_correct_worker_indexes(self): """ Tests that workers would receive a monotonic sequence of ordinal IDs. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) USERS_COUNT = 5 for i in range(USERS_COUNT): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(USERS_COUNT, USERS_COUNT) > self.assertEqual(USERS_COUNT * 2, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2753: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ____________ TestMasterRunner.test_spawn_fewer_locusts_than_workers ____________ self = def test_spawn_fewer_locusts_than_workers(self): class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(2, 2) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2726: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected __________________ TestMasterRunner.test_spawn_uneven_locusts __________________ self = def test_spawn_uneven_locusts(self): """ Tests that we can accurately spawn a certain number of locusts, even if it's not an even number of the connected workers """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2705: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ______________________ TestMasterRunner.test_start_event _______________________ self = def test_start_event(self): """ Tests that test_start event is fired """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) run_count = [0] @self.environment.events.test_start.add_listener def on_test_start(*a, **kw): run_count[0] += 1 for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2580: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected _______________________ TestMasterRunner.test_stop_event _______________________ self = def test_stop_event(self): """ Tests that test_stop event is fired """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) @self.environment.events.test_stopping.add_listener def on_test_stopping(*_, **__): self.runner_stopping = True @self.environment.events.test_stop.add_listener def on_test_stop(*_, **__): self.runner_stopped = True for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2619: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected ____________________ TestMasterRunner.test_stop_event_quit _____________________ self = def test_stop_event_quit(self): """ Tests that test_stop event is fired when quit() is called directly """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) @self.environment.events.test_stopping.add_listener def on_test_stopping(*_, **__): self.runner_stopping = True @self.environment.events.test_stop.add_listener def on_test_stop(*_, **__): self.runner_stopped = True for i in range(5): server.mocked_send(Message("client_ready", __version__, "fake_client%i" % i)) master.start(7, 7) > self.assertEqual(10, len(server.outbox)) E AssertionError: 10 != 0 locust/test/test_runners.py:2658: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client0). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client4). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected __________ TestMasterRunner.test_unknown_host_sends_message_to_master __________ self = def test_unknown_host_sends_message_to_master(self): """ Validate master ignores message that is sent from unknown host """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3217: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. _____________________ TestMasterRunner.test_worker_connect _____________________ self = def test_worker_connect(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:2083: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. __________ TestMasterRunner.test_worker_connect_with_special_versions __________ self = def test_worker_connect_with_special_versions(self): with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner() server.mocked_send(Message("client_ready", None, "1.x_style_client_should_not_be_allowed")) self.assertEqual(1, len(self.mocked_log.error)) self.assertEqual(0, len(master.clients)) server.mocked_send(Message("client_ready", "abcd", "other_version_mismatch_should_just_give_a_warning")) self.assertEqual(1, len(self.mocked_log.warning)) self.assertEqual(1, len(master.clients)) server.mocked_send(Message("client_ready", -1, "version_check_bypass_should_not_warn")) self.assertEqual(1, len(self.mocked_log.warning)) self.assertEqual(2, len(master.clients)) server.mocked_send( Message("client_ready", __version__ + "1", "difference_in_patch_version_should_not_warn") ) self.assertEqual(3, len(master.clients)) > self.assertEqual(1, len(self.mocked_log.warning)) E AssertionError: 1 != 2 locust/test/test_runners.py:2111: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (1.x_style_client_should_not_be_allowed). That's not going to work. WARNING locust.runners:runners.py:1017 A worker (other_version_mismatch_should_just_give_a_warning) running a different version (abcd) connected, master version is INFO locust.runners:runners.py:1028 Worker other_version_mismatch_should_just_give_a_warning (index 0) reported as ready. 1 workers connected. INFO locust.runners:runners.py:1028 Worker version_check_bypass_should_not_warn (index 1) reported as ready. 2 workers connected. WARNING locust.runners:runners.py:1017 A worker (difference_in_patch_version_should_not_warn) running a different version (1) connected, master version is INFO locust.runners:runners.py:1028 Worker difference_in_patch_version_should_not_warn (index 2) reported as ready. 3 workers connected. ______ TestMasterRunner.test_worker_missing_after_heartbeat_dead_interval ______ self = @mock.patch("locust.runners.HEARTBEAT_INTERVAL", new=0.1) @mock.patch("locust.runners.HEARTBEAT_DEAD_INTERNAL", new=-3) def test_worker_missing_after_heartbeat_dead_interval(self): class TestUser(User): @task def my_task(self): gevent.sleep(600) with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server, patch_env( "LOCUST_WAIT_FOR_WORKERS_REPORT_AFTER_RAMP_UP", "0.1" ): master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "fake_client1")) server.mocked_send(Message("client_ready", __version__, "fake_client2")) server.mocked_send(Message("client_ready", __version__, "fake_client3")) master.start(3, 3) server.mocked_send(Message("spawning", None, "fake_client1")) server.mocked_send(Message("spawning", None, "fake_client2")) server.mocked_send(Message("spawning", None, "fake_client3")) sleep(0.1) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client1", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client2", ) ) server.mocked_send( Message( "heartbeat", {"state": STATE_RUNNING, "current_cpu_usage": 50, "current_memory_usage": 200, "count": 1}, "fake_client3", ) ) sleep(0.1) # initially all workers are in active state self.assertEqual(0, len(master.clients.missing)) > self.assertEqual(3, master.worker_count) E AssertionError: 3 != 0 locust/test/test_runners.py:2308: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client1). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client2). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (fake_client3). That's not going to work. WARNING locust.runners:runners.py:743 You can't start a distributed test before at least one worker processes has connected WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client1. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client2. Asking worker to quit. WARNING locust.runners:runners.py:1115 Got spawning message from unknown worker fake_client3. Asking worker to quit. ___________ TestMasterRunner.test_worker_sends_bad_message_to_master ___________ self = def test_worker_sends_bad_message_to_master(self): """ Validate master sends reconnect message to worker when it receives a bad message. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3166: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. ______ TestMasterRunner.test_worker_sends_unrecognized_message_to_master _______ self = def test_worker_sends_unrecognized_message_to_master(self): """ Validate master ignores message from worker when it cannot parse adddress info. """ class TestUser(User): @task def my_task(self): pass with mock.patch("locust.rpc.rpc.Server", mocked_rpc()) as server: master = self.get_runner(user_classes=[TestUser]) server.mocked_send(Message("client_ready", __version__, "zeh_fake_client1")) > self.assertEqual(1, len(master.clients)) E AssertionError: 1 != 0 locust/test/test_runners.py:3194: AssertionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (zeh_fake_client1). That's not going to work. _______________________ TestCsvStats.test_stats_history ________________________ self = def test_stats_history(self): env1 = Environment(events=locust.events, catch_exceptions=False) runner1 = env1.create_master_runner("127.0.0.1", 5558) env2 = Environment(events=locust.events, catch_exceptions=False) > runner2 = env2.create_worker_runner("127.0.0.1", 5558) locust/test/test_stats.py:589: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ locust/env.py:153: in create_worker_runner return self._create_runner( locust/env.py:115: in _create_runner self.runner = runner_class(self, *args, **kwargs) locust/runners.py:1216: in __init__ self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() locust/runners.py:1445: in connect_to_master self.connect_to_master() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = def connect_to_master(self): self.retry += 1 self.client.send(Message("client_ready", __version__, self.client_id)) try: success = self.connection_event.wait(timeout=CONNECT_TIMEOUT) except KeyboardInterrupt: # dont complain about getting CTRL-C sys.exit(1) if not success: if self.retry < 3: logger.debug( f"Failed to connect to master {self.master_host}:{self.master_port}, retry {self.retry}/{CONNECT_RETRY_COUNT}." ) else: logger.warning( f"Failed to connect to master {self.master_host}:{self.master_port}, retry {self.retry}/{CONNECT_RETRY_COUNT}." ) if self.retry > CONNECT_RETRY_COUNT: > raise ConnectionError() E ConnectionError locust/runners.py:1444: ConnectionError ------------------------------ Captured log call ------------------------------- ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 3/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 4/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 5/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 6/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 7/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 8/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 9/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 10/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 11/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 12/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 13/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 14/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 15/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 16/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 17/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 18/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 19/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 20/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 21/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 22/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 23/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 24/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 25/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 26/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 27/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 28/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 29/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 30/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 31/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 32/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 33/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 34/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 35/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 36/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 37/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 38/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 39/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 40/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 41/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 42/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 43/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 44/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 45/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 46/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 47/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 48/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 49/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 50/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 51/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 52/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 53/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 54/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 55/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 56/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 57/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 58/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 59/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 60/60. ERROR locust.runners:runners.py:1009 An old (pre 2.0) worker tried to connect (i-capture-the-hostname_a29a633d9a714780a8750e08cd37b0f3). That's not going to work. WARNING locust.runners:runners.py:1440 Failed to connect to master 127.0.0.1:5558, retry 61/60. =============================== warnings summary =============================== locust/test/test_fasthttp.py::TestFastHttpSsl::test_ssl_request_insecure locust/test/test_web.py::TestWebUIWithTLS::test_index_with_https /usr/lib/python3/dist-packages/gevent/ssl.py:238: DeprecationWarning: ssl.PROTOCOL_TLS is deprecated self._context = SSLContext(ssl_version) -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ FAILED locust/test/test_load_locustfile.py::TestLoadLocustfile::test_locustfile_from_url FAILED locust/test/test_log.py::TestLoggingOptions::test_log_to_file - OSErro... FAILED locust/test/test_log.py::TestLoggingOptions::test_logging_output - OSE... FAILED locust/test/test_log.py::TestLoggingOptions::test_skip_logging - OSErr... FAILED locust/test/test_log.py::TestLoggingOptions::test_user_broken_on_start FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_load_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_w_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_autostart_wo_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_command_line_user_selection FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_arguments_in_file FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_custom_exit_code FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_default_headless_spawn_options_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_shape_class_names FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_duplicate_userclass_names FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_locustfiles_directory_is_empty FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_no_tasks_match_tags FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_error_when_providing_both_run_time_and_a_shape_class FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_graceful_exit_when_keyboard_interrupt FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_headless_spawn_options_wo_run_time FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_help_arg - ... FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_html_report_option FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_input - Ass... FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_percentile_parameter FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_invalid_stop_timeout_string FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_no_error_when_same_userclass_in_two_files FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_percentile_parameter FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_percentiles_to_statistics FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_autostart_with_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_headless_with_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_run_with_userclass_picker FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_log_disabled_parameters FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_shape_class_with_use_common_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_spawing_with_fixed_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_spawning_with_fixed FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_web_options FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_in_directory FAILED locust/test/test_main.py::StandaloneIntegrationTests::test_webserver_multiple_locustfiles_with_shape FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_events FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_report_timeout_expired FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_tags FAILED locust/test/test_main.py::DistributedIntegrationTests::test_distributed_with_locustfile_distribution_not_plain_filename FAILED locust/test/test_main.py::DistributedIntegrationTests::test_expect_workers FAILED locust/test/test_main.py::DistributedIntegrationTests::test_json_schema FAILED locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution FAILED locust/test/test_main.py::DistributedIntegrationTests::test_locustfile_distribution_with_workers_started_first FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_autodetect FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_ctrl_c FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_error_doesnt_blow_up_completely FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_separate_worker FAILED locust/test/test_main.py::DistributedIntegrationTests::test_processes_workers_quit_unexpected FAILED locust/test/test_main.py::DistributedIntegrationTests::test_worker_indexes FAILED locust/test/test_main.py::DistributedIntegrationTests::test_workers_shut_down_if_master_is_gone FAILED locust/test/test_runners.py::TestMasterRunner::test_attributes_populated_when_calling_start FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_down FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_interval FAILED locust/test/test_runners.py::TestMasterRunner::test_custom_shape_scale_up FAILED locust/test/test_runners.py::TestMasterRunner::test_last_worker_missing_stops_test FAILED locust/test/test_runners.py::TestMasterRunner::test_last_worker_quitting_stops_test FAILED locust/test/test_runners.py::TestMasterRunner::test_master_discard_first_client_ready FAILED locust/test/test_runners.py::TestMasterRunner::test_master_marks_downed_workers_as_missing FAILED locust/test/test_runners.py::TestMasterRunner::test_master_reset_connection FAILED locust/test/test_runners.py::TestMasterRunner::test_rebalance_locust_users_on_worker_connect FAILED locust/test/test_runners.py::TestMasterRunner::test_reset_connection_after_RPCError FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_correct_worker_indexes FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_fewer_locusts_than_workers FAILED locust/test/test_runners.py::TestMasterRunner::test_spawn_uneven_locusts FAILED locust/test/test_runners.py::TestMasterRunner::test_start_event - Asse... FAILED locust/test/test_runners.py::TestMasterRunner::test_stop_event - Asser... FAILED locust/test/test_runners.py::TestMasterRunner::test_stop_event_quit - ... FAILED locust/test/test_runners.py::TestMasterRunner::test_unknown_host_sends_message_to_master FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_connect - A... FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_connect_with_special_versions FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_missing_after_heartbeat_dead_interval FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_sends_bad_message_to_master FAILED locust/test/test_runners.py::TestMasterRunner::test_worker_sends_unrecognized_message_to_master FAILED locust/test/test_stats.py::TestCsvStats::test_stats_history - Connecti... = 84 failed, 464 passed, 1 skipped, 15 deselected, 2 warnings in 528.82s (0:08:48) = E: pybuild pybuild:389: test: plugin custom failed with: exit code=1: PYTHONPATH=/build/reproducible-path/locust-2.24.0/.pybuild/cpython3_3.11_locust/build python3.11 -m pytest -v --ignore=examples/test_data_management.py -k 'not TestMasterWorkerRunners' dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.12 3.11" returned exit code 13 make[1]: [debian/rules:15: override_dh_auto_test] Error 25 (ignored) make[1]: Leaving directory '/build/reproducible-path/locust-2.24.0' create-stamp debian/debhelper-build-stamp fakeroot debian/rules binary dh binary --with python3 --buildsystem=pybuild dh_testroot -O--buildsystem=pybuild dh_prep -O--buildsystem=pybuild dh_auto_install --destdir=debian/python3-locust/ -O--buildsystem=pybuild I: pybuild plugin_pyproject:178: Copying package built for python3.12 to destdir I: pybuild plugin_pyproject:178: Copying package built for python3.11 to destdir dh_installdocs -O--buildsystem=pybuild dh_installchangelogs -O--buildsystem=pybuild debian/rules override_dh_installexamples make[1]: Entering directory '/build/reproducible-path/locust-2.24.0' dh_installexamples -X.pyc make[1]: Leaving directory '/build/reproducible-path/locust-2.24.0' dh_python3 -O--buildsystem=pybuild dh_installsystemduser -O--buildsystem=pybuild dh_perl -O--buildsystem=pybuild dh_link -O--buildsystem=pybuild dh_strip_nondeterminism -O--buildsystem=pybuild dh_compress -O--buildsystem=pybuild dh_fixperms -O--buildsystem=pybuild dh_missing -O--buildsystem=pybuild dh_installdeb -O--buildsystem=pybuild dh_gencontrol -O--buildsystem=pybuild dpkg-gencontrol: warning: Recommends field of package python3-locust: substitution variable ${python3:Recommends} used, but is not defined dpkg-gencontrol: warning: Suggests field of package python3-locust: substitution variable ${python3:Suggests} used, but is not defined dh_md5sums -O--buildsystem=pybuild dh_builddeb -O--buildsystem=pybuild dpkg-deb: building package 'python3-locust' in '../python3-locust_2.24.0-1_all.deb'. dpkg-genbuildinfo --build=binary -O../locust_2.24.0-1_i386.buildinfo dpkg-genchanges --build=binary -O../locust_2.24.0-1_i386.changes dpkg-genchanges: info: binary-only upload (no source code included) dpkg-source --after-build . dpkg-source: info: using options from locust-2.24.0/debian/source/options: --extend-diff-ignore=^[^/]+.egg-info/ dpkg-buildpackage: info: binary-only upload (no source included) dpkg-genchanges: info: including full source code in upload I: copying local configuration I: user script /srv/workspace/pbuilder/54022/tmp/hooks/B01_cleanup starting I: user script /srv/workspace/pbuilder/54022/tmp/hooks/B01_cleanup finished I: unmounting dev/ptmx filesystem I: unmounting dev/pts filesystem I: unmounting dev/shm filesystem I: unmounting proc filesystem I: unmounting sys filesystem I: cleaning the build env I: removing directory /srv/workspace/pbuilder/54022 and its subdirectories I: Current time: Thu Mar 21 18:19:29 +14 2024 I: pbuilder-time-stamp: 1710994769