From a8a74a70faa54dc9fa58db52bedfd41278a249f4 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Wed, 5 May 2021 22:44:36 -0700 Subject: [PATCH] examples/ssh_server_fork: Support the multi-client through pthread so the same code base demo both multi-process and multi-thread model Signed-off-by: Xiang Xiao Reviewed-by: Jakub Jelen Change-Id: I98554a99b7a31586be37abde7c357f81a05c3d6e --- examples/CMakeLists.txt | 8 +++- examples/{ssh_server_fork.c => ssh_server.c} | 39 +++++++++++++++++++- 2 files changed, 43 insertions(+), 4 deletions(-) rename examples/{ssh_server_fork.c => ssh_server.c} (96%) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 4e09083a..49c19183 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -37,9 +37,13 @@ if (UNIX AND NOT WIN32) if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H)) if (HAVE_LIBUTIL) - add_executable(ssh_server_fork ssh_server_fork.c) - target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) + add_executable(ssh_server_fork ssh_server.c) + target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -DWITH_FORK) target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util) + + add_executable(ssh_server_pthread ssh_server.c) + target_compile_options(ssh_server_pthread PRIVATE ${DEFAULT_C_COMPILE_FLAGS}) + target_link_libraries(ssh_server_pthread ssh::ssh ${ARGP_LIBRARY} pthread util) endif (HAVE_LIBUTIL) if (WITH_GSSAPI AND GSSAPI_FOUND) diff --git a/examples/ssh_server_fork.c b/examples/ssh_server.c similarity index 96% rename from examples/ssh_server_fork.c rename to examples/ssh_server.c index 7f939d21..24c494e7 100644 --- a/examples/ssh_server_fork.c +++ b/examples/ssh_server.c @@ -24,6 +24,7 @@ The goal is to show the API in action. #ifdef HAVE_LIBUTIL_H #include #endif +#include #ifdef HAVE_PTY_H #include #endif @@ -783,18 +784,38 @@ static void handle_session(ssh_event event, ssh_session session) { } } +#ifdef WITH_FORK /* SIGCHLD handler for cleaning up dead children. */ static void sigchld_handler(int signo) { (void) signo; while (waitpid(-1, NULL, WNOHANG) > 0); } +#else +static void *session_thread(void *arg) { + ssh_session session = arg; + ssh_event event; + + event = ssh_event_new(); + if (event != NULL) { + /* Blocks until the SSH session ends by either + * child thread exiting, or client disconnecting. */ + handle_session(event, session); + ssh_event_free(event); + } else { + fprintf(stderr, "Could not create polling context\n"); + } + ssh_disconnect(session); + ssh_free(session); + return NULL; +} +#endif int main(int argc, char **argv) { ssh_bind sshbind; ssh_session session; - ssh_event event; - struct sigaction sa; int rc; +#ifdef WITH_FORK + struct sigaction sa; /* Set up SIGCHLD handler. */ sa.sa_handler = sigchld_handler; @@ -804,6 +825,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Failed to register SIGCHLD handler\n"); return 1; } +#endif rc = ssh_init(); if (rc < 0) { @@ -844,6 +866,9 @@ int main(int argc, char **argv) { /* Blocks until there is a new incoming connection. */ if(ssh_bind_accept(sshbind, session) != SSH_ERROR) { +#ifdef WITH_FORK + ssh_event event; + switch(fork()) { case 0: /* Remove the SIGCHLD handler inherited from parent. */ @@ -869,6 +894,16 @@ int main(int argc, char **argv) { case -1: fprintf(stderr, "Failed to fork\n"); } +#else + pthread_t tid; + + rc = pthread_create(&tid, NULL, session_thread, session); + if (rc == 0) { + pthread_detach(tid); + continue; + } + fprintf(stderr, "Failed to pthread_create\n"); +#endif } else { fprintf(stderr, "%s\n", ssh_get_error(sshbind)); }