nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.25k stars 321 forks source link

Ruby isolation rootfs pytest reliably fails #1238

Open ac000 opened 2 months ago

ac000 commented 2 months ago

The below test reliably fails, though generally only for ruby 3.2, the 3.3 tests generally always succeed.

Rerunning it usually works... (sometimes it needs a few runs)

test/test_ruby_isolation.py::test_ruby_isolation_rootfs ERROR

==================================== ERRORS ====================================
_______________ ERROR at teardown of test_ruby_isolation_rootfs ________________

request = <SubRequest 'run' for <Function test_ruby_isolation_rootfs>>

    @pytest.fixture(autouse=True)
    def run(request):
        unit = unit_run()

        option.skip_alerts = [
            r'read signalfd\(4\) failed',
            r'sendmsg.+failed',
            r'recvmsg.+failed',
        ]
        option.skip_sanitizer = False

        _fds_info['main']['skip'] = False
        _fds_info['router']['skip'] = False
        _fds_info['controller']['skip'] = False

        yield

        # stop unit

        error_stop_unit = unit_stop()
        error_stop_processes = stop_processes()

        # prepare log

        with Log.open() as f:
            log = f.read()
            Log.set_pos(f.tell())

        if not option.save_log and option.restart:
            shutil.rmtree(unit['temp_dir'])
            Log.set_pos(0)

        # clean temp_dir before the next test

        if not option.restart:
            _clear_conf(log=log)
>           _clear_temp_dir()

test/conftest.py:238: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    def _clear_temp_dir():
        temporary_dir = unit_instance['temp_dir']

        if is_findmnt and not waitforunmount(temporary_dir, timeout=600):
>           sys.exit('Could not unmount filesystems in tmpdir ({temporary_dir}).')
E           SystemExit: Could not unmount filesystems in tmpdir ({temporary_dir}).

test/conftest.py:432: SystemExit
=================================== FAILURES ===================================
__________________________ test_ruby_isolation_rootfs __________________________

is_su = True, require = <function check_prerequisites at 0x7f20b43a9ab0>
temp_dir = '/tmp/unit-test-1mcvwuuu'

    def test_ruby_isolation_rootfs(is_su, require, temp_dir):
        isolation = {'rootfs': temp_dir}

        if not is_su:
            require(
                {
                    'features': {
                        'isolation': [
                            'unprivileged_userns_clone',
                            'user',
                            'mnt',
                            'pid',
                        ]
                    }
                }
            )

            isolation['namespaces'] = {
                'mount': True,
                'credential': True,
                'pid': True,
            }

        client.load('status_int', isolation=isolation)

        assert 'success' in client.conf(
            '"/ruby/status_int/config.ru"',
            'applications/status_int/script',
        )

        assert 'success' in client.conf(
            '"/ruby/status_int"',
            'applications/status_int/working_directory',
        )

>       assert client.get()['status'] == 200, 'status int'

test/test_ruby_isolation.py:43: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
test/unit/http.py:165: in get
    return self.http('GET', **kwargs)
test/unit/http.py:103: in http
    resp = self.recvall(sock, **recvall_kwargs).decode(
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <unit.applications.lang.ruby.ApplicationRuby object at 0x7f20b4418250>
sock = <socket.socket fd=5, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 43988), raddr=('127.0.0.1', 8080)>
kwargs = {}, timeout_default = 60, timeout = 60, buff_size = 4096, data = b''
rlist = []

    def recvall(self, sock, **kwargs):
        timeout_default = 60

        timeout = kwargs.get('read_timeout', timeout_default)
        buff_size = kwargs.get('buff_size', 4096)

        data = b''
        while True:
            rlist = select.select([sock], [], [], timeout)[0]
            if not rlist:
                # For all current cases if the "read_timeout" was changed
                # than test do not expect to get a response from server.
                if timeout == timeout_default:
>                   pytest.fail("Can't read response from server.")
E                   Failed: Can't read response from server.

test/unit/http.py:189: Failed
=========================== short test summary info ============================
FAILED test/test_ruby_isolation.py::test_ruby_isolation_rootfs - Failed: Can't read response from server.
ERROR test/test_ruby_isolation.py::test_ruby_isolation_rootfs - SystemExit: Could not unmount filesystems in tmpdir ({temporary_dir}).
========= 1 failed, 38 passed, 7 skipped, 1 error in 132.93s (0:02:12) =========