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 <xiaoxiang@xiaomi.com> Reviewed-by: Jakub Jelen <jjelen@redhat.com> Change-Id: I98554a99b7a31586be37abde7c357f81a05c3d6e
Этот коммит содержится в:
родитель
3b29e2ad4c
Коммит
a8a74a70fa
@ -37,9 +37,13 @@ if (UNIX AND NOT WIN32)
|
|||||||
|
|
||||||
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
|
if (WITH_SERVER AND (ARGP_LIBRARY OR HAVE_ARGP_H))
|
||||||
if (HAVE_LIBUTIL)
|
if (HAVE_LIBUTIL)
|
||||||
add_executable(ssh_server_fork ssh_server_fork.c)
|
add_executable(ssh_server_fork ssh_server.c)
|
||||||
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS})
|
target_compile_options(ssh_server_fork PRIVATE ${DEFAULT_C_COMPILE_FLAGS} -DWITH_FORK)
|
||||||
target_link_libraries(ssh_server_fork ssh::ssh ${ARGP_LIBRARY} util)
|
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)
|
endif (HAVE_LIBUTIL)
|
||||||
|
|
||||||
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
if (WITH_GSSAPI AND GSSAPI_FOUND)
|
||||||
|
@ -24,6 +24,7 @@ The goal is to show the API in action.
|
|||||||
#ifdef HAVE_LIBUTIL_H
|
#ifdef HAVE_LIBUTIL_H
|
||||||
#include <libutil.h>
|
#include <libutil.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
#ifdef HAVE_PTY_H
|
#ifdef HAVE_PTY_H
|
||||||
#include <pty.h>
|
#include <pty.h>
|
||||||
#endif
|
#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. */
|
/* SIGCHLD handler for cleaning up dead children. */
|
||||||
static void sigchld_handler(int signo) {
|
static void sigchld_handler(int signo) {
|
||||||
(void) signo;
|
(void) signo;
|
||||||
while (waitpid(-1, NULL, WNOHANG) > 0);
|
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) {
|
int main(int argc, char **argv) {
|
||||||
ssh_bind sshbind;
|
ssh_bind sshbind;
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_event event;
|
|
||||||
struct sigaction sa;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
#ifdef WITH_FORK
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
/* Set up SIGCHLD handler. */
|
/* Set up SIGCHLD handler. */
|
||||||
sa.sa_handler = 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");
|
fprintf(stderr, "Failed to register SIGCHLD handler\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
rc = ssh_init();
|
rc = ssh_init();
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
@ -844,6 +866,9 @@ int main(int argc, char **argv) {
|
|||||||
|
|
||||||
/* Blocks until there is a new incoming connection. */
|
/* Blocks until there is a new incoming connection. */
|
||||||
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
if(ssh_bind_accept(sshbind, session) != SSH_ERROR) {
|
||||||
|
#ifdef WITH_FORK
|
||||||
|
ssh_event event;
|
||||||
|
|
||||||
switch(fork()) {
|
switch(fork()) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Remove the SIGCHLD handler inherited from parent. */
|
/* Remove the SIGCHLD handler inherited from parent. */
|
||||||
@ -869,6 +894,16 @@ int main(int argc, char **argv) {
|
|||||||
case -1:
|
case -1:
|
||||||
fprintf(stderr, "Failed to fork\n");
|
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 {
|
} else {
|
||||||
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
fprintf(stderr, "%s\n", ssh_get_error(sshbind));
|
||||||
}
|
}
|
Загрузка…
x
Ссылка в новой задаче
Block a user