Wait using a condition variable in server

Currently, server_stop() is called from the same thread as
server_connect_to(), so interruption may never happen.

This is a step to prepare executing the server from a dedicated thread.
This commit is contained in:
Romain Vimont 2021-10-31 14:56:37 +01:00
parent a54dc8212f
commit 5b9c88693e
2 changed files with 45 additions and 4 deletions

View file

@ -367,7 +367,8 @@ connect_and_read_byte(sc_socket socket, uint16_t port) {
}
static sc_socket
connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
connect_to_server(struct server *server, uint32_t attempts, sc_tick delay) {
uint16_t port = server->local_port;
do {
LOGD("Remaining connection attempts: %d", (int) attempts);
sc_socket socket = net_socket();
@ -381,7 +382,20 @@ connect_to_server(uint16_t port, uint32_t attempts, uint32_t delay) {
net_close(socket);
}
if (attempts) {
SDL_Delay(delay);
sc_mutex_lock(&server->mutex);
sc_tick deadline = sc_tick_now() + delay;
bool timed_out = false;
while (!server->stopped && !timed_out) {
timed_out = !sc_cond_timedwait(&server->cond_stopped,
&server->mutex, deadline);
}
bool stopped = server->stopped;
sc_mutex_unlock(&server->mutex);
if (stopped) {
LOGI("Connection attempt stopped");
break;
}
}
} while (--attempts > 0);
return SC_INVALID_SOCKET;
@ -395,7 +409,23 @@ server_init(struct server *server, const struct server_params *params) {
return false;
}
ok = sc_mutex_init(&server->mutex);
if (!ok) {
LOGE("Could not create server mutex");
server_params_destroy(&server->params);
return false;
}
ok = sc_cond_init(&server->cond_stopped);
if (!ok) {
LOGE("Could not create server cond_stopped");
sc_mutex_destroy(&server->mutex);
server_params_destroy(&server->params);
return false;
}
server->process = SC_PROCESS_NONE;
server->stopped = false;
server->server_socket = SC_INVALID_SOCKET;
server->video_socket = SC_INVALID_SOCKET;
@ -453,8 +483,8 @@ server_connect_to(struct server *server, struct server_info *info) {
server->server_socket = SC_INVALID_SOCKET;
} else {
uint32_t attempts = 100;
uint32_t delay = 100; // ms
video_socket = connect_to_server(server->local_port, attempts, delay);
sc_tick delay = SC_TICK_FROM_MS(100);
video_socket = connect_to_server(server, attempts, delay);
if (video_socket == SC_INVALID_SOCKET) {
goto fail;
}
@ -563,6 +593,11 @@ error:
void
server_stop(struct server *server) {
sc_mutex_lock(&server->mutex);
server->stopped = true;
sc_cond_signal(&server->cond_stopped);
sc_mutex_unlock(&server->mutex);
if (server->server_socket != SC_INVALID_SOCKET) {
if (!net_interrupt(server->server_socket)) {
LOGW("Could not interrupt server socket");
@ -627,4 +662,6 @@ server_destroy(struct server *server) {
}
}
server_params_destroy(&server->params);
sc_cond_destroy(&server->cond_stopped);
sc_mutex_destroy(&server->mutex);
}

View file

@ -47,6 +47,10 @@ struct server {
// alive only between start() and stop()
struct sc_process_observer observer;
sc_mutex mutex;
sc_cond cond_stopped;
bool stopped;
sc_socket server_socket; // only used if !tunnel_forward
sc_socket video_socket;
sc_socket control_socket;