all: remove pthread

This commit is contained in:
Shuanglei Tao
2019-09-15 18:09:48 +08:00
parent 4ad0cc86b7
commit 5381d0f825
5 changed files with 45 additions and 91 deletions

View File

@@ -67,7 +67,7 @@ add_custom_command(OUTPUT html.h
list(APPEND SOURCE_FILES html.h) list(APPEND SOURCE_FILES html.h)
set(INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR} ${LIBWEBSOCKETS_INCLUDE_DIR} ${JSON-C_INCLUDE_DIR}) set(INCLUDE_DIRS ${OPENSSL_INCLUDE_DIR} ${LIBWEBSOCKETS_INCLUDE_DIR} ${JSON-C_INCLUDE_DIR})
set(LINK_LIBS pthread ${OPENSSL_LIBRARIES} ${LIBWEBSOCKETS_LIBRARIES} ${JSON-C_LIBRARY}) set(LINK_LIBS ${OPENSSL_LIBRARIES} ${LIBWEBSOCKETS_LIBRARIES} ${JSON-C_LIBRARY})
if(APPLE) if(APPLE)
# required for the new homebrew version of libwebsockets # required for the new homebrew version of libwebsockets

View File

@@ -61,10 +61,11 @@ check_auth(struct lws *wsi, struct pss_http *pss) {
return AUTH_FAIL; return AUTH_FAIL;
} }
void access_log(struct lws *wsi, const char *path) { void
access_log(struct lws *wsi, const char *path) {
char rip[50]; char rip[50];
#if LWS_LIBRARY_VERSION_MAJOR > 2 || (LWS_LIBRARY_VERSION_MAJOR ==2 && LWS_LIBRARY_VERSION_MINOR >=4) #if LWS_LIBRARY_VERSION_NUMBER >= 2004000
lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip)); lws_get_peer_simple(lws_get_network_wsi(wsi), rip, sizeof(rip));
#else #else
char name[100]; char name[100];

View File

@@ -7,9 +7,6 @@
#include <errno.h> #include <errno.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/queue.h> #include <sys/queue.h>
#include <sys/select.h>
#include <sys/types.h>
#include <pthread.h>
#if defined(__OpenBSD__) || defined(__APPLE__) #if defined(__OpenBSD__) || defined(__APPLE__)
#include <util.h> #include <util.h>
@@ -111,7 +108,6 @@ check_host_origin(struct lws *wsi) {
void void
tty_client_remove(struct tty_client *client) { tty_client_remove(struct tty_client *client) {
pthread_mutex_lock(&server->mutex);
struct tty_client *iterator; struct tty_client *iterator;
LIST_FOREACH(iterator, &server->clients, list) { LIST_FOREACH(iterator, &server->clients, list) {
if (iterator == client) { if (iterator == client) {
@@ -120,7 +116,6 @@ tty_client_remove(struct tty_client *client) {
break; break;
} }
} }
pthread_mutex_unlock(&server->mutex);
} }
void void
@@ -130,12 +125,6 @@ tty_client_destroy(struct tty_client *client) {
client->running = false; client->running = false;
if (pthread_mutex_trylock(&client->mutex) == 0) {
client->state = STATE_DONE;
pthread_cond_signal(&client->cond);
pthread_mutex_unlock(&client->mutex);
}
// kill process (group) and free resource // kill process (group) and free resource
int pgid = getpgid(client->pid); int pgid = getpgid(client->pid);
int pid = pgid > 0 ? -pgid : client->pid; int pid = pgid > 0 ? -pgid : client->pid;
@@ -159,8 +148,6 @@ cleanup:
free(client->args[i]); free(client->args[i]);
} }
pthread_mutex_destroy(&client->mutex);
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000 #if LWS_LIBRARY_VERSION_NUMBER >= 3002000
lws_sul_schedule(context, 0, &client->sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL); lws_sul_schedule(context, 0, &client->sul_stagger, NULL, LWS_SET_TIMER_USEC_CANCEL);
#endif #endif
@@ -169,20 +156,8 @@ cleanup:
tty_client_remove(client); tty_client_remove(client);
} }
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000 int
void spawn_process(struct tty_client *client) {
stagger_callback(lws_sorted_usec_list_t *sul) {
struct tty_client *client = lws_container_of(sul, struct tty_client, sul_stagger);
lws_callback_on_writable(client->wsi);
lws_sul_schedule(context, 0, sul, stagger_callback, 10 * LWS_US_PER_MS);
}
#endif
void *
thread_run_command(void *args) {
struct tty_client *client = (struct tty_client *) args;
// append url args to arguments // append url args to arguments
char *argv[server->argc + client->argc + 1]; char *argv[server->argc + client->argc + 1];
int i, n = 0; int i, n = 0;
@@ -195,11 +170,10 @@ thread_run_command(void *args) {
argv[n] = NULL; argv[n] = NULL;
int pty; int pty;
fd_set des_set;
pid_t pid = forkpty(&pty, NULL, NULL, NULL); pid_t pid = forkpty(&pty, NULL, NULL, NULL);
if (pid < 0) { /* error */ if (pid < 0) { /* error */
lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno)); lwsl_err("forkpty failed: %d (%s)\n", errno, strerror(errno));
pthread_exit((void *) 1); return 1;
} else if (pid == 0) { /* child */ } else if (pid == 0) { /* child */
setenv("TERM", server->terminal_type, true); setenv("TERM", server->terminal_type, true);
// Don't pass the web socket onto child processes // Don't pass the web socket onto child processes
@@ -217,32 +191,24 @@ thread_run_command(void *args) {
if (client->size.ws_row > 0 && client->size.ws_col > 0) if (client->size.ws_row > 0 && client->size.ws_col > 0)
ioctl(client->pty, TIOCSWINSZ, &client->size); ioctl(client->pty, TIOCSWINSZ, &client->size);
while (client->running) { return 0;
}
void
tty_client_poll(struct tty_client *client) {
if (!client->running || client->state == STATE_READY) return;
fd_set des_set;
FD_ZERO (&des_set); FD_ZERO (&des_set);
FD_SET (pty, &des_set); FD_SET (client->pty, &des_set);
struct timeval tv = { 1, 0 }; struct timeval tv = { 0, 0 };
int ret = select(pty + 1, &des_set, NULL, NULL, &tv); if (select(client->pty + 1, &des_set, NULL, NULL, &tv) <= 0) return;
if (ret == 0) continue;
if (ret < 0) break;
if (FD_ISSET (pty, &des_set)) { if (FD_ISSET (client->pty, &des_set)) {
while (client->running) {
pthread_mutex_lock(&client->mutex);
while (client->state == STATE_READY) {
pthread_cond_wait(&client->cond, &client->mutex);
}
memset(client->pty_buffer, 0, sizeof(client->pty_buffer)); memset(client->pty_buffer, 0, sizeof(client->pty_buffer));
client->pty_len = read(pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE); client->pty_len = read(client->pty, client->pty_buffer + LWS_PRE + 1, BUF_SIZE);
client->state = STATE_READY; client->state = STATE_READY;
pthread_mutex_unlock(&client->mutex);
break;
} }
}
if (client->pty_len <= 0) break;
}
pthread_exit((void *) 0);
} }
int int
@@ -294,17 +260,12 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
} }
} }
pthread_mutex_init(&client->mutex, NULL);
pthread_cond_init(&client->cond, NULL);
pthread_mutex_lock(&server->mutex);
LIST_INSERT_HEAD(&server->clients, client, list); LIST_INSERT_HEAD(&server->clients, client, list);
server->client_count++; server->client_count++;
pthread_mutex_unlock(&server->mutex);
lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI); lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_GET_URI);
#if LWS_LIBRARY_VERSION_MAJOR > 2 || (LWS_LIBRARY_VERSION_MAJOR ==2 && LWS_LIBRARY_VERSION_MINOR >=4) #if LWS_LIBRARY_VERSION_NUMBER >= 2004000
lws_get_peer_simple(lws_get_network_wsi(wsi), client->address, sizeof(client->address)); lws_get_peer_simple(lws_get_network_wsi(wsi), client->address, sizeof(client->address));
#else #else
char name[100]; char name[100];
@@ -328,8 +289,9 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
lws_callback_on_writable(wsi); lws_callback_on_writable(wsi);
break; break;
} }
if (client->state != STATE_READY) if (client->state != STATE_READY) {
break; break;
}
// read error or client exited, close connection // read error or client exited, close connection
if (client->pty_len == 0) { if (client->pty_len == 0) {
@@ -371,10 +333,6 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
// check if there are more fragmented messages // check if there are more fragmented messages
if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) { if (lws_remaining_packet_payload(wsi) > 0 || !lws_is_final_fragment(wsi)) {
return 0; return 0;
} else {
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
lws_sul_schedule(context, 0, &client->sul_stagger, stagger_callback, 10);
#endif
} }
switch (command) { switch (command) {
@@ -414,9 +372,7 @@ callback_tty(struct lws *wsi, enum lws_callback_reasons reason,
return -1; return -1;
} }
} }
int err = pthread_create(&client->thread, NULL, thread_run_command, client); if (spawn_process(client) != 0) {
if (err != 0) {
lwsl_err("pthread_create return: %d\n", err);
return 1; return 1;
} }
break; break;

View File

@@ -4,7 +4,6 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <getopt.h> #include <getopt.h>
#include <pthread.h>
#include <signal.h> #include <signal.h>
#include <sys/stat.h> #include <sys/stat.h>
@@ -165,7 +164,6 @@ tty_server_free(struct tty_server *ts) {
unlink(ts->socket_path); unlink(ts->socket_path);
} }
} }
pthread_mutex_destroy(&ts->mutex);
free(ts); free(ts);
} }
@@ -229,6 +227,15 @@ calc_command_start(int argc, char **argv) {
return start; return start;
} }
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000
void
stagger_callback(lws_sorted_usec_list_t *sul) {
struct tty_client *client = lws_container_of(sul, struct tty_client, sul_stagger);
lws_callback_on_writable(client->wsi);
}
#endif
int int
main(int argc, char **argv) { main(int argc, char **argv) {
if (argc == 1) { if (argc == 1) {
@@ -238,7 +245,6 @@ main(int argc, char **argv) {
int start = calc_command_start(argc, argv); int start = calc_command_start(argc, argv);
server = tty_server_new(argc, argv, start); server = tty_server_new(argc, argv, start);
pthread_mutex_init(&server->mutex, NULL);
struct lws_context_creation_info info; struct lws_context_creation_info info;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
@@ -476,27 +482,21 @@ main(int argc, char **argv) {
open_uri(url); open_uri(url);
} }
// libwebsockets main loop
while (!force_exit) { while (!force_exit) {
pthread_mutex_lock(&server->mutex);
if (!LIST_EMPTY(&server->clients)) { if (!LIST_EMPTY(&server->clients)) {
struct tty_client *client; struct tty_client *client;
LIST_FOREACH(client, &server->clients, list) { LIST_FOREACH(client, &server->clients, list) {
if (client->running && pthread_mutex_trylock(&client->mutex) == 0) { tty_client_poll(client);
if (client->state != STATE_DONE)
lws_callback_on_writable(client->wsi);
else
pthread_cond_signal(&client->cond);
pthread_mutex_unlock(&client->mutex);
}
}
}
pthread_mutex_unlock(&server->mutex);
lws_service(context, 10);
#if LWS_LIBRARY_VERSION_NUMBER >= 3002000 #if LWS_LIBRARY_VERSION_NUMBER >= 3002000
usleep(10 * LWS_US_PER_MS); lws_sul_schedule(context, 0, &client->sul_stagger, stagger_callback, 0);
#else
lws_callback_on_writable(client->wsi);
#endif #endif
} }
}
lws_service(context, 0);
usleep(10 * 1000); // 10ms
}
lws_context_destroy(context); lws_context_destroy(context);

View File

@@ -1,4 +1,3 @@
#include <pthread.h>
#include <stdbool.h> #include <stdbool.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/queue.h> #include <sys/queue.h>
@@ -48,9 +47,6 @@ struct tty_client {
enum pty_state state; enum pty_state state;
char pty_buffer[LWS_PRE + 1 + BUF_SIZE]; char pty_buffer[LWS_PRE + 1 + BUF_SIZE];
ssize_t pty_len; ssize_t pty_len;
pthread_t thread;
pthread_mutex_t mutex;
pthread_cond_t cond;
LIST_ENTRY(tty_client) list; LIST_ENTRY(tty_client) list;
}; };
@@ -80,7 +76,6 @@ struct tty_server {
bool once; // whether accept only one client and exit on disconnection bool once; // whether accept only one client and exit on disconnection
char socket_path[255]; // UNIX domain socket path char socket_path[255]; // UNIX domain socket path
char terminal_type[30]; // terminal type to report char terminal_type[30]; // terminal type to report
pthread_mutex_t mutex;
}; };
extern int extern int
@@ -89,3 +84,5 @@ callback_http(struct lws *wsi, enum lws_callback_reasons reason, void *user, voi
extern int extern int
callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len);
extern void
tty_client_poll(struct tty_client *client);