- Set app cache dir as temp directory for mkstemp() to avoid EACCES
on Android sandbox (iperf_set_test_template).
- Wrap all MethodChannel callbacks in MainThreadCallback with
Handler(Looper.getMainLooper()) to prevent SIGABRT from calling
invokeMethod from native reader thread.
- Add setTempDir JNI function and logging for test return value.
Two root causes prevented iperf3 tests from running:
1. argv[0] bug: iperf_parse_arguments() expects argv[0] to be the
program name. We passed Dart args directly, so argv[0] was '-c',
which iperf3 misinterpreted as the program name → 'Argument parse
error: must either be a client (-c) or server (-s)'. Fixed by
prepending "iperf3" as argv[0] and shifting user args to argv[1+].
2. Signal handling: iperf_catch_sigend() installs handlers that use
longjmp() to a jmp_buf, but we never initialized the buffer with
setjmp(). Any signal during iperf_run_client() caused SIGSEGV or
hang. Added setjmp/longjmp wrapper matching main.c's pattern,
SIGPIPE=SIG_IGN, and a 30s connect_timeout to avoid DNS hangs.
Also extracted iperf_cleanup_and_signal() to deduplicate the
normal-return and longjmp paths. Added diagnostic logging to
IperfRunner.kt's library loading for faster future debugging.
The root cause of the SIGBUS (alignment fault) crash was casting jmethodID
values to function pointers and invoking them directly. jmethodID is an
opaque JNI type that must only be used via CallVoidMethod/CallObjectMethod
etc. Calling it as a function pointer dereferences garbage memory, causing
SIGBUS at address 0xb1.
Changes:
- Replace function pointer typedefs (output_callback_t etc.) with a struct
storing JNIEnv + callback global ref + jmethodIDs
- All callbacks now go through CallVoidMethod(env, ref, mid, ...)
- Remove getTestProgress() (never used, unused start_time workaround)
- Fix Kotlin arg cast: List<String> -> toTypedArray() (ClassCastException)
- Update UI default server to speedtest.uztelecom.uz
- Switch from bundled iperf3 binary (Process.start) to JNI compilation
- iperf3 3.21 source API was incompatible (start_time, iperf_strerror, etc.)
- iperf3 3.19 source is proven to work (used by CellularLab)
- CMakeLists.txt updated: config.h generated into cpp/iperf/ for correct include paths
- iperf_jni.c fixed for 3.19 API (no start_time on iperf_test)
- getTestProgress() returns g_test->duration as fallback (no real-time elapsed tracking yet)
- NDK CMake pinned to 3.22.1
- UI layer updated: removed Iperf3BinaryPathProvider references
- Tests updated: TestRunViewModelTest matches new service interface
- pubspec.yaml: removed iperf3 assets bundle, added http dependency
- AndroidManifest: INTERNET permission (needed for hostname resolution)
- Android toybox ash cannot exec ELF binaries even with -rwx permissions
- runInShell: true wraps in /system/bin/sh -c which refuses ELF
- runInShell: false calls execve() directly, bypassing sh
- Added debugPrint logging to capture actual output in logcat
- Added static analysis results (flutter analyze + flutter test)
- Added on-device test results from Sony XQ-AS72 (QV7100JQ52)
- iperf3 v3.21 executes successfully without permission errors
- Raw output displayed in text box, status shows 'Test complete'
- The original chmod call used Process.run('chmod', ...) which fails on Android
because chmod is not available in the app sandbox PATH
- /system/bin/sh is always present on Android and can execute chmod on the
extracted binary, setting executable permissions before the first run
- Move MainActivity.kt from novoyuuparosk.iperf3gui to
com.novoyuuparosk.iperf3gui package directory
- Update package declaration to match namespace
- This fixes the ClassNotFoundException crash on launch
- Add GitHub Actions CI workflow for analyze and tests
- Update README with project structure, build instructions, and license info
- Document iperf3 binary bundling process
- Use const Iperf3Result constructor in tests
- Remove unused import from widget_test.dart
- Fix unnecessary underscore warnings in Consumer builders
- Use initializing formal for iperf3Service field
- Wire up main.dart to call Iperf3BinaryPathProvider.initialize()