From fdb6498e98d8af2443c100b9826a51c7ec3680c4 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 28 Jul 2026 15:58:14 -0500 Subject: [PATCH 1/6] Updated Termux platform instructions in INSTALL Ticket: none Changelog: none --- INSTALL | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/INSTALL b/INSTALL index 75dc6b27d6..6553789ff0 100644 --- a/INSTALL +++ b/INSTALL @@ -157,10 +157,12 @@ sudo apk add alpine-sdk lmdb-dev openssl-dev bison flex-dev acl-dev pcre2-dev au Note that in order for process promises to work you must install the procps package for a "proper" ps command instead of busybox. -* Termux (2020-04-24) +* Termux (2025-10-10) -pkg install build-essential git autoconf automake bison flex liblmdb openssl pcre2 libacl libyaml -./autogen.sh --without-pam +pkg install build-essential git autoconf automake bison flex liblmdb openssl pcre2 libacl libyaml binutils librsync +# maybe binutils-is-llvm - Use llvm as binutils instead of binutils to get ld +LDFLAGS='-landroid-glob' ./autogen.sh --without-pam --prefix=$PREFIX --with-workdir=$PREFIX/var/lib/cfengine --without-systemd-service --without-selinux-policy +make && make install * OSX (2021-10-20) From 44b52b146f7f9c491b70b4524e1d86bd8ec07f18 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 28 Jul 2026 15:58:46 -0500 Subject: [PATCH 2/6] Added Termux platform support in ci build and configure scripts Ticket: none Changelog: none --- ci/build.sh | 5 ++++- ci/configure.sh | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 3bd306e6e8..3e47dfc761 100755 --- a/ci/build.sh +++ b/ci/build.sh @@ -5,7 +5,10 @@ set -ex thisdir="$(dirname "$0")" cd "$thisdir"/.. -source /etc/os-release +if [ -f /etc/os-release ]; then + source /etc/os-release +fi + CFLAGS="-Wall" if [ "$ID" != "alpine" ]; then CFLAGS="$CFLAGS -Werror" diff --git a/ci/configure.sh b/ci/configure.sh index dc66f9f7ed..e47d02b6e1 100755 --- a/ci/configure.sh +++ b/ci/configure.sh @@ -4,15 +4,24 @@ set -ex thisdir="$(dirname "$0")" cd "$thisdir"/.. -OPTS="--enable-debug" +OPTS="--config-cache --enable-debug" -source /etc/os-release -if [ "$ID" = "alpine" ]; then - OPTS="" # we don't want --enable-debug so that libpromises/dbm_test_api is not built due to lack of srand48_r() and friends on alpine linux libmusl +if [ -f /etc/os-release ]; then + source /etc/os-release + if [ "$ID" = "alpine" ]; then + OPTS="" # we don't want --enable-debug so that libpromises/dbm_test_api is not built due to lack of srand48_r() and friends on alpine linux libmusl + fi fi if [ -n "$TERMUX_VERSION" ] || [ "$ID" = "alpine" ]; then OPTS="$OPTS --without-pam" fi +if [ -n "$TERMUX_VERSION" ]; then + export LDFLAGS+=" -landroid-glob" + OPTS="$OPTS --prefix=$PREFIX\ + --with-workdir=$PREFIX/var/lib/cfengine \ + --without-selinux-policy \ + --without-systemd-service" +fi ./autogen.sh $OPTS From 294f6be3c6bda1c58d40ba933e6d18a0d1409167 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 28 Jul 2026 15:59:35 -0500 Subject: [PATCH 3/6] Adjusted IsReadable() to not use pthread_cancel() on Termux platform instead use MaskTerminationSignalsInThread() from libntech Ticket: CFE-4401 Changelog: title --- configure.ac | 8 ++++++++ libpromises/evalfunction.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/configure.ac b/configure.ac index ac3bc601e4..6a31e42346 100644 --- a/configure.ac +++ b/configure.ac @@ -182,6 +182,14 @@ CC="$PTHREAD_CC" CFLAGS="$PTHREAD_CFLAGS $CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" +dnl ###################################################################### +dnl libpromises/evalfunction.c isreadable() uses pthread_cancel so check +dnl if available and reverts to pthread_kill if not. +dnl This check must come after ACX_PTHREAD is called so that CC, CFLAGS, +dnl and LIBS are appropriately set for the local pthreads situation. +dnl ###################################################################### +AC_CHECK_FUNCS([pthread_cancel]) + dnl ###################################################################### dnl Whether to build extensions as builtin extensions or a separate dnl plugin. The default is plugin. diff --git a/libpromises/evalfunction.c b/libpromises/evalfunction.c index 8dfcdc8e42..8571a61c55 100644 --- a/libpromises/evalfunction.c +++ b/libpromises/evalfunction.c @@ -86,6 +86,7 @@ #include #include /* ThreadWait */ #include +#include /* MaskTerminationSignalsInThread */ #include @@ -9774,10 +9775,32 @@ struct IsReadableThreadData bool success; }; +#ifndef HAVE_PTHREAD_CANCEL +#define PTHREAD_CANCELED ((void *)-1) +static void ThreadSignalHandler(int signum) +{ + pthread_exit(PTHREAD_CANCELED); +} +#endif + static void *IsReadableThreadRoutine(void *data) { assert(data != NULL); +/* + * Termux environment has no pthread_cancel() so use MaskTerminationSignalsInThread() and pthread_kill() + */ +#ifndef HAVE_PTHREAD_CANCEL + MaskTerminationSignalsInThread(); + struct sigaction actions; + memset(&actions, 0, sizeof(actions)); + sigemptyset(&actions.sa_mask); + actions.sa_flags = 0; + actions.sa_handler = ThreadSignalHandler; + sigaction(SIGHUP, &actions, NULL); + MaskTerminationSignalsInThread(); +#endif + struct IsReadableThreadData *const thread_data = data; // Give main thread time to call pthread_cond_timedwait(3) @@ -9929,7 +9952,11 @@ static FnCallResult FnCallIsReadable(ARG_UNUSED EvalContext *const ctx, "Read operation timed out, exceeded %ld seconds.", path, timeout); +#ifdef HAVE_PTHREAD_CANCEL ret = pthread_cancel(thread_data.thread); +#else + ret = pthread_kill(thread_data.thread, SIGUSR2); +#endif if (ret != 0) { Log(LOG_LEVEL_ERR, "Failed to cancel thread"); @@ -9959,10 +9986,12 @@ static FnCallResult FnCallIsReadable(ARG_UNUSED EvalContext *const ctx, return FnFailure(); } +#ifdef HAVE_PTHREAD_CANCEL if (status == PTHREAD_CANCELED) { Log(LOG_LEVEL_DEBUG, "Thread was canceled"); } +#endif return FnReturnContext(success); } From 7604f0292ddb6daf4be6112e4f4193399cedb758 Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 28 Jul 2026 16:00:36 -0500 Subject: [PATCH 4/6] Fixed check for copy_file_range on Android AC_CHECK_FUNCS apparently doesn't take into account the __ANDROID_API__ level properly and so incorrectly determines that copy_file_range is available for termux at API 24 but copy_file_range is <= 34. Ticket: none Changelog: none --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6a31e42346..6544163a29 100644 --- a/configure.ac +++ b/configure.ac @@ -1355,7 +1355,7 @@ AC_CHECK_DECLS([FALLOC_FL_PUNCH_HOLE], [], [], [ ]) AC_CHECK_HEADERS([sys/sendfile.h]) AC_CHECK_FUNCS([sendfile]) -AC_CHECK_FUNCS([copy_file_range]) +AC_CHECK_DECL([copy_file_range]) dnl ####################################################################### From 1feb8ab44b32b00c2230c5726d687e12d86c52fa Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Tue, 28 Jul 2026 16:01:45 -0500 Subject: [PATCH 5/6] Adjusted dbm_test_api.c to build on alpine linux with musl libc The re-entrant versions of srand() and friends aren't technically required and not using them enables compilation on platforms without glibc. Ticket: none Changelog: none --- libpromises/dbm_test_api.c | 11 ++++++----- libpromises/dbm_test_api.h | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libpromises/dbm_test_api.c b/libpromises/dbm_test_api.c index def4d50b92..0ea5ba94e7 100644 --- a/libpromises/dbm_test_api.c +++ b/libpromises/dbm_test_api.c @@ -22,8 +22,9 @@ included file COSL.txt. */ +#ifndef __ANDROID__ #include -#include /* lrand48_r() */ +#include /* lrand48() */ #include /* usleep(), syscall()/gettid() */ #include /* xstrndup() */ #include @@ -70,23 +71,22 @@ static void DBItemDestroy(DBItem *item) } } -static __thread struct drand48_data rng_data; static void InitializeRNG(long int seed) { - srand48_r(seed, &rng_data); + srand48(seed); } static long GetRandomNumber(long limit) { long rnd_val; - lrand48_r(&rng_data, &rnd_val); /* generates a value in the [0, 2^31) interval */ + rnd_val = lrand48(); const long random_max = ((0x80000000 - 1) / limit) * limit; while (rnd_val > random_max) { /* got a bad value past the greatest multiple of the limit interval, * retry (see "modulo bias" if this is unclear) */ - lrand48_r(&rng_data, &rnd_val); + rnd_val = lrand48(); } return rnd_val % limit; } @@ -735,3 +735,4 @@ void RemoveFilament(DBFilament *filament) free(filament); CloseDB(db); } +#endif /* not __ANDROID__ */ diff --git a/libpromises/dbm_test_api.h b/libpromises/dbm_test_api.h index ffda177d75..a6fe0ae63d 100644 --- a/libpromises/dbm_test_api.h +++ b/libpromises/dbm_test_api.h @@ -22,6 +22,7 @@ included file COSL.txt. */ +#ifndef __ANDROID__ #ifndef CFENGINE_DBM_TEST_API_H #define CFENGINE_DBM_TEST_API_H @@ -55,3 +56,4 @@ DBFilament *FillUpDB(dbid db_id, int usage_pct); void RemoveFilament(DBFilament *filament); #endif /* CFENGINE_DBM_TEST_API_H */ +#endif /* not __ANDROID__ */ From 477f0d906f0429701d8032cda0836814a656605d Mon Sep 17 00:00:00 2001 From: Craig Comstock Date: Thu, 30 Jul 2026 15:09:59 -0500 Subject: [PATCH 6/6] Temporary bump for libntech craigcomstock/cfe-4401 branch that leaves out MaskTerminationSignalsInThread() on mingw platform That function has unsupported functions on mingw platform with pthreads-w32. Remove this commit when https://github.com/NorthernTechHQ/libntech/pull/287 is merged --- libntech | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libntech b/libntech index 90fa0bc2fa..0b42abd55b 160000 --- a/libntech +++ b/libntech @@ -1 +1 @@ -Subproject commit 90fa0bc2fa2404332c4ec04743b305cab65ac4cf +Subproject commit 0b42abd55bded89d45a5099d2546df838716cda9