From aaf52df0b00727ec87da3136ae975174c7b6d7bc Mon Sep 17 00:00:00 2001 From: slipher Date: Fri, 7 Aug 2026 18:27:15 -0500 Subject: [PATCH 01/16] command_tester: Use SIGINT first on timed-out test On *nix platforms, try sending SIGINT first to a timed-out test process, then send SIGKILL after 3 seconds. This gives the test the chance to do cleanup, particularly of child processes. Contrary to the belief of a prior author, killing a process does not ensure that descendants of that process are also killed. --- pynacl/platform.py | 4 +++- tools/test_lib.py | 30 ++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pynacl/platform.py b/pynacl/platform.py index ca637936d5..b0e1ec60d4 100644 --- a/pynacl/platform.py +++ b/pynacl/platform.py @@ -200,7 +200,7 @@ def PlatformTripleSaigo(platform=None, machine=None): def KillSubprocessAndChildren(proc): """Kill a subprocess and all children. - While this is trivial on Posix platforms, on Windows this requires some + On Windows this requires some method for walking the process tree. Relying on this functionality in the taskkill.exe utility for now. @@ -210,8 +210,10 @@ def KillSubprocessAndChildren(proc): if IsWindows(): # Do subprocess call as the process may terminate before we manage # to invoke taskkill. + # TODO: use job object instead? subprocess.call( [os.path.join(os.environ['SYSTEMROOT'], 'System32', 'taskkill.exe'), '/F', '/T', '/PID', str(proc.pid)]) else: + # TODO: implement for *nix. This kills only the one process proc.kill() diff --git a/tools/test_lib.py b/tools/test_lib.py index 23739369d9..5e35504b4e 100755 --- a/tools/test_lib.py +++ b/tools/test_lib.py @@ -115,29 +115,27 @@ def CommunicateWithTimeout(proc, input_data=None, timeout=None): if timeout == 0: timeout = None - result = [] - def Target(): - result.append(list(proc.communicate(input_data))) - - thread = threading.Thread(target=Target) - thread.start() - thread.join(timeout) - if thread.is_alive(): + try: + out, err = proc.communicate(input_data, timeout) + except subprocess.TimeoutExpired: sys.stderr.write('\nAttempting to kill test due to timeout!\n') - # This will kill the process which should force communicate to return with - # any partial output. - pynacl.platform.KillSubprocessAndChildren(proc) - # Thus result should ALWAYS contain something after this join. - thread.join() + try: + if pynacl.platform.IsWindows(): + raise # Skip to the kill all part + proc.send_signal(signal.SIGINT) + out, err = result = proc.communicate(timeout=3) + except subprocess.TimeoutExpired: + sys.stderr.write('\nForcibly killing test due to timeout!\n') + pynacl.platform.KillSubprocessAndChildren(proc) + out, err = proc.communicate() msg = '\n\nKilled test due to timeout!\n' sys.stderr.write(msg) # Also append to stderr. - result[0][1] += (msg.encode('ascii') if isinstance(result[0][1], bytes) else msg) + err += (msg.encode('ascii') if isinstance(err, bytes) else msg) returncode = -9 else: returncode = proc.returncode - assert len(result) == 1 - return tuple(result[0]) + (returncode,) + return out, err, returncode def RunTestWithInput(cmd, input_data, timeout=None): From ab2e8b8e7b547b69afb630a8998944279fc53b4a Mon Sep 17 00:00:00 2001 From: slipher Date: Fri, 7 Aug 2026 18:33:03 -0500 Subject: [PATCH 02/16] Make GDB tests stop when timed out On Linux, GDB tests that got deadlocked (for example run_gdb_break_continue_thread_test on ARM) would cause command_tester.py to hang indefinitely because the GDB and sel_ldr processes continued to live after the main test process (the child of command_tester) was killed. Make the main test process respond to SIGINT by killing its children. --- tests/gdb/gdb_test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/gdb/gdb_test.py b/tests/gdb/gdb_test.py index e2f98a9da6..0a2425c79a 100644 --- a/tests/gdb/gdb_test.py +++ b/tests/gdb/gdb_test.py @@ -3,6 +3,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import atexit import json import optparse import os @@ -205,6 +206,7 @@ def __init__(self, options, name): self._gdb = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE) + atexit.register(self.KillProcess) self._expected_success = True def Wait(self): @@ -289,6 +291,7 @@ def Kill(self): def KillProcess(self): self._expected_success = False KillProcess(self._gdb) + atexit.unregister(self.KillProcess) def Eval(self, expression): return self.Command('-data-evaluate-expression ' + expression)[b'value'] From 5fea2a930ccdab3b8568b71b221bc1fee8503059 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 8 Aug 2026 12:37:18 -0500 Subject: [PATCH 03/16] Update tool paths for latest Saigo build illwieckz's latest toolchain build https://github.com/DaemonEngine/saigo-nacl-sdk/releases/tag/v21.0-20260805 adds GDB and renames some binutils binaries. Update scons and run.py accordingly. Also delete the code for finding GDB in a 2nd variant of the NaCl toolchain. --- run.py | 2 +- site_scons/site_tools/naclsdk.py | 35 ++++++++++++-------------------- tests/gdb/nacl.scons | 18 ---------------- 3 files changed, 14 insertions(+), 41 deletions(-) diff --git a/run.py b/run.py index 30fc773c69..89596ffecc 100755 --- a/run.py +++ b/run.py @@ -590,7 +590,7 @@ def FindReadElf(): # Look for Saigo or PNaCl readelf or the system one # The architecture the toolchain was built for generally doesn't matter. - readelves = ['x86_64-nacl-readelf', 'pnacl-readelf', 'readelf'] + readelves = ['nacl-readelf', 'x86_64-nacl-readelf', 'pnacl-readelf', 'readelf'] toolchain_paths = [os.path.join(env.saigo_base, 'bin'), os.path.join(env.pnacl_base, 'bin')] diff --git a/site_scons/site_tools/naclsdk.py b/site_scons/site_tools/naclsdk.py index 28ad4aa639..2777a9e637 100755 --- a/site_scons/site_tools/naclsdk.py +++ b/site_scons/site_tools/naclsdk.py @@ -112,6 +112,13 @@ def _SetEnvForNativeSdk(env, sdk_path): cc = 'clang' if env.Bit('nacl_clang') else 'gcc' cxx = 'clang++' if env.Bit('nacl_clang') else 'g++' + def FindRenamedTool(tool): + # For ones renamed in https://github.com/DaemonEngine/saigo-nacl-sdk/releases/tag/v21.0-20260805 + newname = os.path.join(bin_path, 'nacl-' + tool) + if os.path.exists(newname) or os.path.exists(newname + '.exe'): + return newname + return os.path.join(bin_path, '%s-%s' % (tool_prefix, tool)) + env.Replace(# Replace header and lib paths. # where to put nacl extra sdk headers # TODO(robertm): switch to using the mechanism that @@ -125,18 +132,17 @@ def _SetEnvForNativeSdk(env, sdk_path): AR=os.path.join(bin_path, '%s-ar' % tool_prefix), AS=os.path.join(bin_path, '%s-as' % tool_prefix), ASPP=os.path.join(bin_path, '%s-%s' % (tool_prefix, cc)), - FILECHECK=os.path.join(bin_path, 'FileCheck'), - GDB=os.path.join(bin_path, '%s-gdb' % tool_prefix), + GDB=os.path.join(bin_path, 'nacl-gdb'), # NOTE: use g++ for linking so we can handle C AND C++. LINK=os.path.join(bin_path, '%s-%s' % (tool_prefix, cxx)), # Grrr... and sometimes we really need ld. LD=os.path.join(bin_path, '%s-ld' % tool_prefix) + ld_mode_flag, - RANLIB=os.path.join(bin_path, '%s-ranlib' % tool_prefix), - NM=os.path.join(bin_path, '%s-nm' % tool_prefix), - OBJDUMP=os.path.join(bin_path, '%s-objdump' % tool_prefix), - OBJCOPY=os.path.join(bin_path, '%s-objcopy' % tool_prefix), + RANLIB=FindRenamedTool('ranlib'), + NM=FindRenamedTool('nm'), + OBJDUMP=FindRenamedTool('objdump'), + OBJCOPY='false', STRIP=os.path.join(bin_path, '%s-strip' % tool_prefix), - ADDR2LINE=os.path.join(bin_path, '%s-addr2line' % tool_prefix), + ADDR2LINE='false', BASE_LINKFLAGS=[cc_mode_flag], BASE_CFLAGS=[cc_mode_flag], BASE_CXXFLAGS=[cc_mode_flag], @@ -755,21 +761,6 @@ def FakeInstall(dest, source, env): else: _SetEnvForNativeSdk(env, root) - # Daemon: don't depend on a second NaCl toolchain! - if (env.Bit('bitcode') or env.Bit('nacl_clang')) and env.Bit('build_x86') and \ - not env.Bit('no_gdb_tests') and 'nacl_gdb' not in SCons.Script.ARGUMENTS: - # Get GDB from the nacl-gcc glibc toolchain even when using PNaCl. - # TODO(mseaborn): We really want the nacl-gdb binary to be in a - # separate tarball from the nacl-gcc toolchain, then this step - # will not be necessary. - # See http://code.google.com/p/nativeclient/issues/detail?id=2773 - temp_env = env.Clone() - temp_env.ClearBits('bitcode', 'nacl_clang', 'saigo') - temp_env.SetBits('nacl_glibc') - temp_root = temp_env.GetToolchainDir() - _SetEnvForNativeSdk(temp_env, temp_root) - env.Replace(GDB=temp_env['GDB']) - env.Prepend(LIBPATH='${NACL_SDK_LIB}') # Install our scanner for (potential) linker scripts. diff --git a/tests/gdb/nacl.scons b/tests/gdb/nacl.scons index 2ef028f0f8..0f8555b6d1 100644 --- a/tests/gdb/nacl.scons +++ b/tests/gdb/nacl.scons @@ -17,24 +17,6 @@ if env.UnderWindowsCoverage(): if 'nacl_gdb' in SCons.Script.ARGUMENTS: env.Replace(GDB=SCons.Script.ARGUMENTS['nacl_gdb']) -elif env.Bit('build_arm') or env.Bit('build_mips32'): - if env.UsingEmulator(): - # nacl-gdb is built with ARM support but not MIPS support. - if env.Bit('build_mips32'): - Return() - nacl_x86_toolchain_dir = env.GetToolchainDir(target_arch='x86', - is_pnacl=False, - lib_name='glibc') - nacl_gdb_path = os.path.join(nacl_x86_toolchain_dir, 'bin', 'i686-nacl-gdb') - env.Replace(GDB=nacl_gdb_path) - else: - # Use the system's ARM/MIPS GDB because the NaCl toolchain does not - # include a copy of GDB built to run on ARM/MIPS. - env.Replace(GDB='gdb') - # Unlike nacl-gdb, the system version of GDB does not support the - # "nacl-irt" command. - if env.Bit('tests_use_irt'): - Return() # Disable finalization (which would strip debug metadata), but allow # the sandbox translator where it makes sense. From 74f9e1ab3c11206ab14720a86b892282fa110758 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 8 Aug 2026 17:55:39 -0500 Subject: [PATCH 04/16] Enable GDB tests by default (except ARM Mac) But disable 2 tests on ARM that don't work without GDB speaking XML. --- SConstruct | 2 +- tests/gdb/nacl.scons | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/SConstruct b/SConstruct index a579737e29..6e0754f909 100755 --- a/SConstruct +++ b/SConstruct @@ -388,7 +388,7 @@ def SetUpArgumentBits(env): 'to run the specified test(s) without actually running them. This ' 'argument is a counterpart to built_elsewhere.') - BitFromArgument(env, 'no_gdb_tests', default=True, + BitFromArgument(env, 'no_gdb_tests', default=env.Bit('host_mac_arm64'), desc='Prevents GDB tests from running. If GDB is not available, you can ' 'test everything else by specifying this flag.') diff --git a/tests/gdb/nacl.scons b/tests/gdb/nacl.scons index 0f8555b6d1..7919ea7b93 100644 --- a/tests/gdb/nacl.scons +++ b/tests/gdb/nacl.scons @@ -105,6 +105,10 @@ def AddGdbTest(name, is_broken=False, is_thread_test=False): # is created after continuing (https://github.com/DaemonEngine/native_client/issues/57). no_step = env.Bit('build_arm') or env.Bit('build_mips32') +# Currently GDB builds lack XML support which is needed for some ARM register +# info - see https://github.com/DaemonEngine/saigo-nacl-sdk/issues/9 +no_xml = env.Bit('build_arm') and env.Bit('saigo') + AddGdbTest('complete') AddGdbTest('detach') @@ -115,7 +119,7 @@ using_clang = env.Bit('bitcode') or (env.Bit('nacl_clang') and not env.Bit('saig # https://code.google.com/p/nativeclient/issues/detail?id=4059 AddGdbTest('invalid_memory', - is_broken = (using_clang and not env.UsingEmulator())) + is_broken = no_xml or (using_clang and not env.UsingEmulator())) AddGdbTest('kill') AddGdbTest('remote_get') @@ -129,7 +133,7 @@ AddGdbTest('print_symbol', is_broken=no_step) # TODO(mseaborn): Investigate and enable this test. # http://code.google.com/p/nativeclient/issues/detail?id=3252 AddGdbTest('stack_trace', - is_broken=using_clang and env.Bit('build_arm')) + is_broken=no_xml or (using_clang and env.Bit('build_arm'))) AddGdbTest('step_from_func_start', is_broken=no_step) From 7d11ae94e7c8dda822af1986dc17ad21bebb40e3 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 8 Aug 2026 22:57:29 -0500 Subject: [PATCH 05/16] Fix tests that shouldn't run without --mode nacl --- src/trusted/service_runtime/build.scons | 25 +++++++++++++------------ src/trusted/validator_ragel/build.scons | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/trusted/service_runtime/build.scons b/src/trusted/service_runtime/build.scons index d5bdbb7cda..682543ada8 100644 --- a/src/trusted/service_runtime/build.scons +++ b/src/trusted/service_runtime/build.scons @@ -533,7 +533,7 @@ hello_world_nexe = untrusted_env.File('$STAGING_DIR/hello_world.nexe') # Doesn't work on windows under coverage. # TODO(bradnelson): fix this to work on windows under coverage. if ((not env.Bit('windows') or not env.Bit('coverage_enabled')) and - env.Bit('nacl_static_link')): + env.Bit('nacl_static_link') and UsingNaclMode()): # NOTE: uses validator mmap_test_objs = [env.ComponentObject('mmap_test.c')] mmap_test_exe = env.ComponentProgram( @@ -759,17 +759,18 @@ node = env.CommandSelLdrTestNacl( exit_status='1') env.AddNodeToTestSuite(node, ['small_tests'], 'run_sel_ldr_exe_not_found_test') -# Check that "-F" makes sel_ldr stop after loading the nexe but before running -# it. -nullptr_nexe = untrusted_env.GetTranslatedNexe( - untrusted_env.File('$STAGING_DIR/nullptr$PROGSUFFIX')) +if UsingNaclMode(): + # Check that "-F" makes sel_ldr stop after loading the nexe but before running + # it. + nullptr_nexe = untrusted_env.GetTranslatedNexe( + untrusted_env.File('$STAGING_DIR/nullptr$PROGSUFFIX')) -node = env.CommandSelLdrTestNacl( - 'fuzz_nullptr_test.out', - nullptr_nexe, - size='large', - sel_ldr_flags=['-F']) -env.AddNodeToTestSuite(node, ['large_tests'], 'run_fuzz_nullptr_test') + node = env.CommandSelLdrTestNacl( + 'fuzz_nullptr_test.out', + nullptr_nexe, + size='large', + sel_ldr_flags=['-F']) + env.AddNodeToTestSuite(node, ['large_tests'], 'run_fuzz_nullptr_test') if env.Bit('build_mips32'): text_region_start = 0x00020000 @@ -836,7 +837,7 @@ if env.Bit('build_x86_64'): ) env.AddNodeToTestSuite(node, ['small_tests'], 'run_hello_x32_test') -if env.Bit('build_x86') and env.Bit('nacl_static_link'): +if env.Bit('build_x86') and env.Bit('nacl_static_link') and UsingNaclMode(): RE_HELLO = '^(Hello, World!)$' RE_IDENT = r'^\[[0-9,:.]*\] (e_ident\+1 = ELF)$' diff --git a/src/trusted/validator_ragel/build.scons b/src/trusted/validator_ragel/build.scons index 0ecf5b70b1..9a93b539bc 100644 --- a/src/trusted/validator_ragel/build.scons +++ b/src/trusted/validator_ragel/build.scons @@ -545,7 +545,7 @@ for bits in ['32', '64']: '--bits', bits, tests_mask] + update_option) - env.AddNodeToTestSuite( + if UsingNaclMode(): env.AddNodeToTestSuite( dis_section_test, ['small_tests', 'validator_tests'], node_name='run_dis_section_test_%s' % bits) From 6d60be8d6e6c01b0e056ecaa31530b8e1f774ed9 Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 9 Aug 2026 09:41:30 -0500 Subject: [PATCH 06/16] run.py: fix Windows slash issue with subprocess path --- run.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/run.py b/run.py index 89596ffecc..dcfa67eee5 100755 --- a/run.py +++ b/run.py @@ -470,6 +470,9 @@ def Run(args, cwd=None, verbose=True, exit_on_failure=False, # PNaCl toolchain executables (pnacl-translate, readelf) are scripts # not binaries, so it doesn't want to run on Windows without a shell. use_shell = True if pynacl.platform.IsWindows() else False + if use_shell: + args = args[:] + args[0] = os.path.normpath(args[0]) # Must use \ not / p = subprocess.Popen(args, stdin=stdin_redir, stdout=stdout_redir, stderr=stderr_redir, cwd=cwd, shell=use_shell, encoding='utf-8') From 5fe92406fa4c2741723bedd34da7a922c653cc55 Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 9 Aug 2026 14:20:44 -0500 Subject: [PATCH 07/16] Fix CRLF checkout issue with run_app_lib_test --- tests/app_lib/.gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tests/app_lib/.gitattributes diff --git a/tests/app_lib/.gitattributes b/tests/app_lib/.gitattributes new file mode 100644 index 0000000000..b2e75b19cf --- /dev/null +++ b/tests/app_lib/.gitattributes @@ -0,0 +1,2 @@ +app_lib_test.stdin eol=lf +app_lib_test.stdout eol=lf From 9485c825a92c0de7cf6a32e8c80c04a6a156b419 Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 9 Aug 2026 15:04:29 -0500 Subject: [PATCH 08/16] Mark run_platform_qual_test broken for mingw --- src/trusted/platform_qualify/build.scons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trusted/platform_qualify/build.scons b/src/trusted/platform_qualify/build.scons index c3f867d003..4afcf85534 100644 --- a/src/trusted/platform_qualify/build.scons +++ b/src/trusted/platform_qualify/build.scons @@ -63,7 +63,7 @@ if env.Bit('build_x86') and env.Bit('build_x86'): node = env.CommandTest('platform_qual_test.out', [platform_qual_test]) env.AddNodeToTestSuite( node, ['small_tests'], 'run_platform_qual_test', - is_broken=env.IsRunningUnderValgrind()) + is_broken=env.IsRunningUnderValgrind() or env.Bit('mingw')) cpuallowlist_test = env.ComponentProgram( 'cpuallowlist_test', 'arch/x86/nacl_cpuallowlist_test.c', From fbf161247a8ea0be647aeaafb953ecb91ab224f4 Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 9 Aug 2026 15:18:06 -0500 Subject: [PATCH 09/16] Fix expected exit code for run_ntdll_fallback_test In 22bd955dc5152847bd8b6b7019f381075062f297 I updated the expected return code for run_ntdll_intercept_test but neglected to do the same for run_ntdll_fallback_test. --- src/trusted/service_runtime/build.scons | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/trusted/service_runtime/build.scons b/src/trusted/service_runtime/build.scons index 682543ada8..5f5d653188 100644 --- a/src/trusted/service_runtime/build.scons +++ b/src/trusted/service_runtime/build.scons @@ -666,7 +666,7 @@ if env.Bit('windows') and env.Bit('build_x86_64'): node = env.CommandTest( 'ntdll_fallback_test.out', command=[intercept_test_prog, 'test_fallback'], - exit_status='untrusted_segfault', + exit_status=0xC0000409, stdout_golden=env.File('win/exception_patch/fallback_test.stdout')) env.AddNodeToTestSuite(node, ['small_tests'], 'run_ntdll_fallback_test') From 23cab70f0a260cd56ebb2cb9bce3e37d94556451 Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 11 Aug 2026 23:28:49 -0500 Subject: [PATCH 10/16] Mark run_thread_test flaky on emulator --- tests/threads/nacl.scons | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/threads/nacl.scons b/tests/threads/nacl.scons index 69ffc2dec1..b002ece53a 100644 --- a/tests/threads/nacl.scons +++ b/tests/threads/nacl.scons @@ -41,6 +41,7 @@ node = env.CommandSelLdrTestNacl( # NOTE: this should be a pretty slow test, but its been sped up # to not tickle bug 853 env.AddNodeToTestSuite(node, ['small_tests'], 'run_thread_test', + is_flaky=env.UsingEmulator(), # TODO(khim): reenable it when cause of failure on 32bit Windows glibc # will be found. # See: http://code.google.com/p/nativeclient/issues/detail?id=1690 From 05898a1cb865e1317256bc1287505fff26367c20 Mon Sep 17 00:00:00 2001 From: slipher Date: Wed, 19 Aug 2026 01:00:47 -0500 Subject: [PATCH 11/16] Fix flaky run_thread_suspension_test on x86-64 The TestGettingRegisterSnapshotInSyscallContextSwitch part suspended the thread inside the syscall on all 10000 iterations on most runs. But when the thread did suspend outside it, the test seemingly always failed. The test for the stack pointer value was too strict. --- tests/thread_suspension/suspend_test_host.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/thread_suspension/suspend_test_host.c b/tests/thread_suspension/suspend_test_host.c index 73634955db..39c65ebacb 100644 --- a/tests/thread_suspension/suspend_test_host.c +++ b/tests/thread_suspension/suspend_test_host.c @@ -439,6 +439,8 @@ static void TestGettingRegisterSnapshotInSyscallContextSwitch( struct NaClAppThread *natp; struct NaClSignalContext regs; int iteration; + int inside = 0; + int outside = 0; g_simple_syscall_should_exit = 0; g_simple_syscall_called = 0; @@ -460,15 +462,28 @@ static void TestGettingRegisterSnapshotInSyscallContextSwitch( * otherwise there is a small set of instructions that untrusted * code executes. */ - if (!NaClAppThreadIsSuspendedInSyscall(natp)) { + if (NaClAppThreadIsSuspendedInSyscall(natp)) { + ++inside; + } else { regs.prog_ctr = test_shm->expected_regs.prog_ctr; +#if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 && NACL_BUILD_SUBARCH == 64 + /* + * The compiler turns the call to the trampoline into push rip + * followed by jump, so there are two possible values for the stack + * pointer in untrusted code. + */ + regs.stack_ptr = test_shm->expected_regs.stack_ptr; +#endif RegsUnsetNonCalleeSavedRegisters(®s); + ++outside; } RegsAssertEqual(®s, &test_shm->expected_regs); NaClUntrustedThreadsResumeAll(nap); } + printf("Suspended outside syscall %dx, inside syscall %dx\n", outside, inside); + g_simple_syscall_should_exit = 1; WaitForThreadToExitFully(nap); } From 6ada2a7c2845134eb6678d21d1ebca04577888ea Mon Sep 17 00:00:00 2001 From: slipher Date: Wed, 19 Aug 2026 02:12:10 -0500 Subject: [PATCH 12/16] Comment out line of gdb stack_trace test again Partial revert of commit 8ebf53f48c03fcb11b45e0f75faa13100152da39. Turns out this is still broken on x86-32. --- tests/gdb/stack_trace.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/gdb/stack_trace.py b/tests/gdb/stack_trace.py index a56144f414..fdeb9fe3fe 100644 --- a/tests/gdb/stack_trace.py +++ b/tests/gdb/stack_trace.py @@ -19,8 +19,11 @@ def test_stack_trace(self): result = self.gdb.Command('-stack-list-arguments 1 0 1') self.assertEqual(result[b'stack-args'][0][b'frame'][b'args'][0][b'value'], b'2') - self.assertEqual(result[b'stack-args'][1][b'frame'][b'args'][0][b'value'], - b'1') + # This stopped working somewhere between llvm commits + # ecea8371ff03c15fb3dc27ee4108b98335fd2d63 and + # 1d5d18924d185a4267462479307f1ff9911cb112 + #self.assertEqual(result[b'stack-args'][1][b'frame'][b'args'][0][b'value'], + # b'1') self.gdb.Command('return') self.gdb.ResumeAndExpectStop('finish', 'function-finished') self.assertEqual(self.gdb.Eval('global_var'), b'1') From 3d0f3df511cb3a57efc086ea048b93ebbaeba8b1 Mon Sep 17 00:00:00 2001 From: slipher Date: Sun, 9 Aug 2026 19:39:11 -0500 Subject: [PATCH 13/16] Add CI with Scons builds and tests I used the Azure Pipelines job skeleton from https://github.com/DaemonEngine/native_client/pull/39. But CMake stuff is replaced with Scons since that is the currently functional build system. All 64-bit platforms are running most tests. ARM Linux has the NaCl mode disabled due to SDK defects, so it only runs a few tests. x86 32-bit platforms build everything but don't run tests. Co-authored-by: Thomas Debesse --- .azure-pipeline.yml | 118 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .azure-pipeline.yml diff --git a/.azure-pipeline.yml b/.azure-pipeline.yml new file mode 100644 index 0000000000..07901603fd --- /dev/null +++ b/.azure-pipeline.yml @@ -0,0 +1,118 @@ +trigger: + branches: + include: + - master + +pr: + branches: + include: + - '*' + +strategy: + matrix: + Linux amd64 GCC: + VM_IMAGE: 'ubuntu-22.04' + SDK_PLATFORM: linux-amd64 + APT_PACKAGES: g++-10 + SCONS_BUILD_ARGS: platform=x86-64 --mode=opt-host,nacl --no-clang werror=0 + SCONS_TESTS: small_tests medium_tests large_tests + VPYTHON: pyenv/bin/python + Linux i686 GCC: + VM_IMAGE: 'ubuntu-22.04' + SDK_PLATFORM: linux-amd64 + APT_PACKAGES: g++-i686-linux-gnu + SCONS_BUILD_ARGS: platform=x86-32 --mode=opt-host,nacl --no-clang werror=0 + VPYTHON: pyenv/bin/python + Linux armhf GCC: + # There is an IO bug in qemu-arm from ubuntu-22.04. + VM_IMAGE: 'ubuntu-24.04' + SDK_PLATFORM: linux-amd64 + APT_PACKAGES: g++-arm-linux-gnueabihf qemu-user + SCONS_BUILD_ARGS: platform=arm --mode=opt-host --no-clang werror=0 + SCONS_TESTS: small_tests medium_tests + VPYTHON: pyenv/bin/python + Linux amd64 Clang: + VM_IMAGE: 'ubuntu-22.04' + SDK_PLATFORM: linux-amd64 + SCONS_BUILD_ARGS: platform=x86-64 --mode=opt-host,nacl --clang werror=1 + SCONS_TESTS: small_tests medium_tests large_tests + VPYTHON: pyenv/bin/python + macOS amd64 AppleClang: + VM_IMAGE: 'macOS-15' + SDK_PLATFORM: macos-amd64 + SCONS_BUILD_ARGS: platform=x86-64 --mode=opt-host,nacl --clang werror=1 + SCONS_TESTS: all_tests + VPYTHON: pyenv/bin/python + NPROC_COMMAND: sysctl -n hw.logicalcpu + Windows amd64 MSVC: + VM_IMAGE: 'windows-2025' + SDK_PLATFORM: windows-amd64 + SCONS_BUILD_ARGS: platform=x86-64 --mode=opt-host,nacl --no-clang werror=1 mingw_dir=mingw/mingw + SCONS_TESTS: small_tests medium_tests large_tests disable_tests=run_toolchain_python_tests + VPYTHON: pyenv/Scripts/python + PYTHON_PACKAGES: pywin32 + MINGW_URL: https://github.com/niXman/mingw-builds-binaries/releases/download/16.1.0-rt_v14-rev1/x86_64-16.1.0-release-posix-seh-msvcrt-rt_v14-rev1.7z + Windows i686 MSVC: + VM_IMAGE: 'windows-2025' + SDK_PLATFORM: windows-amd64 + SCONS_BUILD_ARGS: platform=x86-32 --mode=opt-host,nacl --no-clang werror=1 mingw_dir=mingw/mingw + VPYTHON: pyenv/Scripts/python + PYTHON_PACKAGES: pywin32 + MINGW_URL: https://github.com/niXman/mingw-builds-binaries/releases/download/16.1.0-rt_v14-rev1/i686-16.1.0-release-posix-dwarf-msvcrt-rt_v14-rev1.7z + Windows amd64 MinGW: + VM_IMAGE: 'windows-2025' + SDK_PLATFORM: windows-amd64 + SCONS_BUILD_ARGS: platform=x86-64 --mode=opt-host,nacl --no-clang mingw=1 werror=1 mingw_dir=mingw/mingw + SCONS_TESTS: small_tests medium_tests large_tests disable_tests=run_toolchain_python_tests + VPYTHON: pyenv/Scripts/python + PYTHON_PACKAGES: pywin32 + MINGW_URL: https://github.com/niXman/mingw-builds-binaries/releases/download/16.1.0-rt_v14-rev1/x86_64-16.1.0-release-posix-seh-msvcrt-rt_v14-rev1.7z + +pool: + vmImage: $(VM_IMAGE) + +steps: +- bash: | + set -xue + if [ -n "${APT_ARCHITECTURE:-}" ]; then + sudo dpkg --add-architecture "${APT_ARCHITECTURE}" + fi + if [ -n "${APT_PACKAGES:-}" ]; then + sudo apt-get update && sudo apt-get -y -q --no-install-recommends install ${APT_PACKAGES} + fi + python3 -m venv pyenv + # TODO pin scons to a specific version? + $(VPYTHON) -m pip install SCons ${PYTHON_PACKAGES:-} + mkdir sdk + ( + cd sdk + curl -fsSL https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v21.0-20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz -o sdk.tar.xz + tar -xJf sdk.tar.xz + rm sdk.tar.xz + mv * sdk # Rename the top-level dir to sdk + ) + if [ -n "${MINGW_URL:-}" ]; then + mkdir mingw + ( + cd mingw + curl -fsSL $(MINGW_URL) -o mingw.7z + 7z x mingw.7z + rm mingw.7z + mv * mingw # Rename the top-level dir to mingw + ) + fi + displayName: 'Setup' + +- bash: | + set -xue + parallelism="$(${NPROC_COMMAND:-nproc})" + echo "Build parallelism: ${parallelism}" + $(VPYTHON) -m SCons saigo=1 saigo_newlib_dir=sdk/sdk ${SCONS_BUILD_ARGS} all_programs -j${parallelism} --verbose + displayName: 'Build' + +- bash: | + set -xue + parallelism="$(${NPROC_COMMAND:-nproc})" + $(VPYTHON) -m SCons saigo=1 saigo_newlib_dir=sdk/sdk ${SCONS_BUILD_ARGS} ${SCONS_TESTS} -j${parallelism} --verbose --keep-going disable_flaky_tests=1 + condition: and(succeeded(), ne(variables['SCONS_TESTS'], '')) + displayName: 'Test' From 94032b6cfb2902d72c68d49a2a1fa47005e4b8da Mon Sep 17 00:00:00 2001 From: slipher Date: Tue, 11 Aug 2026 22:38:18 -0500 Subject: [PATCH 14/16] CI: Use older Saigo build so we can build ARM nacl --- .azure-pipeline.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.azure-pipeline.yml b/.azure-pipeline.yml index 07901603fd..b480754bfc 100644 --- a/.azure-pipeline.yml +++ b/.azure-pipeline.yml @@ -26,10 +26,10 @@ strategy: Linux armhf GCC: # There is an IO bug in qemu-arm from ubuntu-22.04. VM_IMAGE: 'ubuntu-24.04' - SDK_PLATFORM: linux-amd64 + SDK_PLATFORM: arm-xxx APT_PACKAGES: g++-arm-linux-gnueabihf qemu-user - SCONS_BUILD_ARGS: platform=arm --mode=opt-host --no-clang werror=0 - SCONS_TESTS: small_tests medium_tests + SCONS_BUILD_ARGS: platform=arm --mode=opt-host,nacl --no-clang werror=0 + SCONS_TESTS: no_gdb_tests=1 small_tests medium_tests VPYTHON: pyenv/bin/python Linux amd64 Clang: VM_IMAGE: 'ubuntu-22.04' @@ -86,7 +86,12 @@ steps: mkdir sdk ( cd sdk - curl -fsSL https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v21.0-20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz -o sdk.tar.xz + if [ "$(SDK_PLATFORM)" = "arm-xxx" ]; then + sdk_url='https://dl.illwieckz.net/b/saigo/preview/saigo_newlib_20241119.txz' + else + sdk_url='https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v21.0-20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz' + fi + curl -fsSL "$sdk_url" -o sdk.tar.xz tar -xJf sdk.tar.xz rm sdk.tar.xz mv * sdk # Rename the top-level dir to sdk From df1ca660ad8c32b70d12017cb602a4e8e49a2f91 Mon Sep 17 00:00:00 2001 From: slipher Date: Wed, 12 Aug 2026 19:58:36 -0500 Subject: [PATCH 15/16] CI: try curl retries for flaky github.com dl --- .azure-pipeline.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.azure-pipeline.yml b/.azure-pipeline.yml index b480754bfc..ce96652d2f 100644 --- a/.azure-pipeline.yml +++ b/.azure-pipeline.yml @@ -74,6 +74,9 @@ pool: steps: - bash: | set -xue + CURL() { + curl -fsSL --retry 8 "$@" + } if [ -n "${APT_ARCHITECTURE:-}" ]; then sudo dpkg --add-architecture "${APT_ARCHITECTURE}" fi @@ -91,7 +94,7 @@ steps: else sdk_url='https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v21.0-20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz' fi - curl -fsSL "$sdk_url" -o sdk.tar.xz + CURL "$sdk_url" -o sdk.tar.xz tar -xJf sdk.tar.xz rm sdk.tar.xz mv * sdk # Rename the top-level dir to sdk @@ -100,7 +103,7 @@ steps: mkdir mingw ( cd mingw - curl -fsSL $(MINGW_URL) -o mingw.7z + CURL $(MINGW_URL) -o mingw.7z 7z x mingw.7z rm mingw.7z mv * mingw # Rename the top-level dir to mingw From 02fd650ca50a042cacbc699f7577665b0eac96f9 Mon Sep 17 00:00:00 2001 From: slipher Date: Wed, 19 Aug 2026 23:03:39 -0500 Subject: [PATCH 16/16] CI: test x86-32 --- .azure-pipeline.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.azure-pipeline.yml b/.azure-pipeline.yml index ce96652d2f..6e6f377211 100644 --- a/.azure-pipeline.yml +++ b/.azure-pipeline.yml @@ -19,9 +19,11 @@ strategy: VPYTHON: pyenv/bin/python Linux i686 GCC: VM_IMAGE: 'ubuntu-22.04' + APT_ARCHITECTURE: i386 SDK_PLATFORM: linux-amd64 - APT_PACKAGES: g++-i686-linux-gnu + APT_PACKAGES: g++-i686-linux-gnu libc6:i386 SCONS_BUILD_ARGS: platform=x86-32 --mode=opt-host,nacl --no-clang werror=0 + SCONS_TESTS: small_tests medium_tests large_tests VPYTHON: pyenv/bin/python Linux armhf GCC: # There is an IO bug in qemu-arm from ubuntu-22.04. @@ -92,7 +94,7 @@ steps: if [ "$(SDK_PLATFORM)" = "arm-xxx" ]; then sdk_url='https://dl.illwieckz.net/b/saigo/preview/saigo_newlib_20241119.txz' else - sdk_url='https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v21.0-20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz' + sdk_url='https://github.com/DaemonEngine/saigo-nacl-sdk/releases/download/v20260805/saigosdk-$(SDK_PLATFORM)_21.0-20260805.tar.xz' fi CURL "$sdk_url" -o sdk.tar.xz tar -xJf sdk.tar.xz