From 56d7a91cafb89f529c33daee22fa2e6afc388c3d Mon Sep 17 00:00:00 2001 From: wangjianyu3 Date: Thu, 25 Jun 2026 20:08:53 +0800 Subject: [PATCH] netutils/rexecd: add -t option to serve connections without a thread By default rexecd spawns a detached worker thread per accepted connection to allow concurrent sessions. Add a "-t" runtime option to instead handle each connection inline in the main task, avoiding the per-connection worker stack (CONFIG_NETUTILS_REXECD_STACKSIZE) allocation from the heap. This matters on low-memory targets with limited free heap. With "-t", connections are served strictly one at a time: a long-running or interactive command blocks the accept loop until it finishes. Without it, the existing thread-per-connection behaviour is unchanged. Assisted-by: GitHubCopilot:claude-4.8-opus Signed-off-by: wangjianyu3 --- netutils/rexecd/rexecd.c | 63 +++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/netutils/rexecd/rexecd.c b/netutils/rexecd/rexecd.c index 13864a8419c..2ae489b6de2 100644 --- a/netutils/rexecd/rexecd.c +++ b/netutils/rexecd/rexecd.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -164,11 +165,13 @@ static FAR void *doit(pthread_addr_t pvarg) static void usage(FAR const char *progname) { - fprintf(stderr, "Usage: %s [-4|-6|-r]\n", progname); + fprintf(stderr, "Usage: %s [-4|-6|-r] [-t]\n", progname); fprintf(stderr, "Remote Execution Daemon:\n" " -4, Specify address family to AF_INET(default)\n" " -6, Specify address family to AF_INET6\n" - " -r, Specify address family to AF_RPMSG\n"); + " -r, Specify address family to AF_RPMSG\n" + " -t, Serve each connection inline without spawning a" + " per-connection thread (saves heap, no concurrency)\n"); exit(EXIT_FAILURE); } @@ -177,6 +180,7 @@ int main(int argc, FAR char **argv) struct sockaddr_storage addr; pthread_attr_t attr; pthread_t tid; + bool threadless = false; int family; int option; int serv; @@ -184,7 +188,7 @@ int main(int argc, FAR char **argv) int ret; family = AF_INET; - while ((option = getopt(argc, argv, "46r")) != ERROR) + while ((option = getopt(argc, argv, "46rt")) != ERROR) { switch (option) { @@ -197,6 +201,9 @@ int main(int argc, FAR char **argv) case 'r': family = AF_RPMSG; break; + case 't': + threadless = true; + break; default: usage(argv[0]); } @@ -241,22 +248,26 @@ int main(int argc, FAR char **argv) goto err_out; } - ret = pthread_attr_init(&attr); - if (ret != 0) + if (!threadless) { - goto err_out; - } + ret = pthread_attr_init(&attr); + if (ret != 0) + { + goto err_out; + } - ret = pthread_attr_setstacksize(&attr, CONFIG_NETUTILS_REXECD_STACKSIZE); - if (ret != 0) - { - goto attr_out; - } + ret = pthread_attr_setstacksize(&attr, + CONFIG_NETUTILS_REXECD_STACKSIZE); + if (ret != 0) + { + goto attr_out; + } - ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (ret != 0) - { - goto attr_out; + ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + if (ret != 0) + { + goto attr_out; + } } while (1) @@ -275,15 +286,27 @@ int main(int argc, FAR char **argv) } } - ret = pthread_create(&tid, &attr, doit, (pthread_addr_t)sock); - if (ret < 0) + if (threadless) { - close(sock); + doit((pthread_addr_t)(long)sock); + } + else + { + ret = pthread_create(&tid, &attr, doit, + (pthread_addr_t)(long)sock); + if (ret < 0) + { + close(sock); + } } } attr_out: - pthread_attr_destroy(&attr); + if (!threadless) + { + pthread_attr_destroy(&attr); + } + err_out: syslog(LOG_ERR, "rexecd failed ret:%d errno:%d\n", ret, errno); close(serv);