Graceful C-c termination 1/2

This commit is contained in:
x3 2022-01-09 18:45:19 +01:00
parent 9a00b28279
commit 6cf62ab039
Signed by: x3
GPG Key ID: 7E9961E8AD0E240E
7 changed files with 132 additions and 25 deletions

View File

@ -15,6 +15,7 @@
#include "config.h"
#include "ed2k.h"
#include "util.h"
#include "globals.h"
/* Needed, bcuz of custom %B format */
#pragma GCC diagnostic push
@ -409,10 +410,12 @@ void api_free()
uio_error("Cannot cancel api keepalive thread");
} else {
int je = pthread_join(api_ka_thread, NULL);
if (je != 0) {
if (je != 0)
uio_error("Cannot join api keepalive thread: %s",
strerror(je));
}
else
uio_debug("Keepalive thread ended");
if (pthread_mutex_destroy(&api_work_mx) != 0)
uio_error("Cannot destroy api work mutex");
}
@ -473,21 +476,33 @@ static void api_ratelimit()
}
}
/*
* Returns the written byte count
* Or -1 on error, and -2 if errno was EINTR
*/
static ssize_t api_send(char *buffer, size_t data_len, size_t buf_size)
{
ssize_t read_len;
int en;
api_ratelimit();
uio_debug("{Api}: Sending: %.*s", (int)data_len, buffer);
if (api_encryption)
data_len = api_encrypt(buffer, data_len);
if (net_send(buffer, data_len) == -1) {
uio_error("Cannot send data: %s", strerror(errno));
return -1;
}
en = net_send(buffer, data_len);
if (en < 0)
return en;
read_len = net_read(buffer, buf_size);
if (read_len < 0) {
uio_error("!!! BAD PLACE EINTR !!! report pls");
return en; /* This could lead so some problems if we also want to
log out. If we hit this, the msg got sent, but we
couldn't read the response. That means, in the
logout call, this msg's data will be read
Let's see if this ever comes up */
}
api_ratelimit_sent();
if (api_encryption)
@ -566,8 +581,11 @@ enum error api_cmd_version(struct api_result *res)
enum error err = NOERR;
pthread_mutex_lock(&api_work_mx);
if (res_len == -1) {
err = ERR_API_COMMFAIL;
if (res_len < 0) {
if (res_len == -2 && should_exit)
err = ERR_SHOULD_EXIT;
else
err = ERR_API_COMMFAIL;
goto end;
}
@ -607,8 +625,11 @@ static enum error api_cmd_auth(const char *uname, const char *pass,
sizeof(buffer));
enum error err = NOERR;
if (res_len == -1) {
err = ERR_API_COMMFAIL;
if (res_len < 0) {
if (res_len == -2 && should_exit)
err = ERR_SHOULD_EXIT;
else
err = ERR_API_COMMFAIL;
goto end;
}
@ -653,8 +674,11 @@ static enum error api_cmd_logout(struct api_result *res)
long code;
enum error err = NOERR;
if (res_len == -1) {
err = ERR_API_COMMFAIL;
if (res_len < 0) {
if (res_len == -2 && should_exit)
err = ERR_SHOULD_EXIT;
else
err = ERR_API_COMMFAIL;
goto end;
}
@ -683,8 +707,11 @@ enum error api_cmd_uptime(struct api_result *res)
long code;
enum error err = NOERR;
if (res_len == -1) {
err = ERR_API_COMMFAIL;
if (res_len < 0) {
if (res_len == -2 && should_exit)
err = ERR_SHOULD_EXIT;
else
err = ERR_API_COMMFAIL;
goto end;
}
@ -729,8 +756,11 @@ enum error api_cmd_mylistadd(int64_t size, const uint8_t *hash,
api_session, size, hash_str, ml_state, watched),
sizeof(buffer));
if (res_len == -1) {
err = ERR_API_COMMFAIL;
if (res_len < 0) {
if (res_len == -2 && should_exit)
err = ERR_SHOULD_EXIT;
else
err = ERR_API_COMMFAIL;
goto end;
}

View File

@ -1,17 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include "config.h"
#include "error.h"
#include "uio.h"
#include "cmd.h"
#include "globals.h"
bool should_exit = false;
static void signal_handler(int signum, siginfo_t *info, void *ctx)
{
should_exit = true;
printf("\033[0GGot C-c. Press again to force exit\n");
}
int main(int argc, char **argv)
{
int exit_code = EXIT_SUCCESS;
enum error err = config_parse(argc, argv);
enum error err;
struct sigaction sact = {
.sa_flags = SA_SIGINFO | SA_RESETHAND,
//.sa_flags = SA_SIGINFO,
.sa_sigaction = signal_handler,
};
if (sigaction(SIGINT, &sact, NULL) != 0) {
uio_error("Cannot set up signal handler: %s", strerror(errno));
return EXIT_FAILURE;
}
err = config_parse(argc, argv);
if (err == ERR_OPT_EXIT)
return EXIT_SUCCESS;
else if (err != NOERR)
@ -20,7 +42,9 @@ int main(int argc, char **argv)
//config_dump();
err = cmd_main();
if (err != NOERR)
if (err == ERR_SHOULD_EXIT)
uio_debug("Exiting as requested orz");
else if (err != NOERR)
exit_code = EXIT_FAILURE;
config_free();

View File

@ -3,10 +3,12 @@
#include <string.h>
#include <errno.h>
#include <ftw.h>
#include <assert.h>
#include "ed2k.h"
#include "ed2k_util.h"
#include "uio.h"
#include "globals.h"
static struct ed2k_util_opts l_opts;
@ -15,11 +17,13 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
{
unsigned char buf[blksize], hash[ED2K_HASH_SIZE];
struct ed2k_ctx ed2k;
enum error err;
FILE *f;
size_t read_len;
int en;
if (l_opts.pre_hash_fn) {
enum error err = l_opts.pre_hash_fn(file_path, st, l_opts.data);
err = l_opts.pre_hash_fn(file_path, st, l_opts.data);
if (err == ED2KUTIL_DONTHASH)
return NOERR;
else if (err != NOERR)
@ -28,24 +32,52 @@ static enum error ed2k_util_hash(const char *file_path, blksize_t blksize,
f = fopen(file_path, "rb");
if (!f) {
uio_error("Failed to open file: %s (%s)", file_path, strerror(errno));
return ERR_ED2KUTIL_FS;
en = errno;
uio_error("Failed to open file: %s (%s)", file_path, strerror(en));
if (en == EINTR && should_exit)
return ERR_SHOULD_EXIT;
else
return ERR_ED2KUTIL_FS;
}
ed2k_init(&ed2k);
read_len = fread(buf, 1, sizeof(buf), f);
while (read_len > 0) {
/* From my test, fread wont return anything special on signal interrupt */
while (read_len > 0 && !should_exit) {
ed2k_update(&ed2k, buf, read_len);
read_len = fread(buf, 1, sizeof(buf), f);
}
// TODO check if eof or error
if (should_exit) {
err = ERR_SHOULD_EXIT;
goto fail;
}
if (ferror(f)) { /* Loop stopped bcuz of error, not EOF */
uio_error("Failure while reading file");
err = ERR_ED2KUTIL_FS;
goto fail;
}
assert(feof(f));
ed2k_final(&ed2k, hash);
fclose(f);
if (fclose(f) != 0) {
en = errno;
uio_debug("Fclose failed: %s", strerror(en));
if (en == EINTR && should_exit)
return ERR_SHOULD_EXIT;
else
return ERR_ED2KUTIL_FS;
}
if (l_opts.post_hash_fn)
return l_opts.post_hash_fn(file_path, hash, st, l_opts.data);
return NOERR;
fail:
if (f) /* We can't get a 2nd interrupt now */
fclose(f);
return err;
}
static int ed2k_util_walk(const char *fpath, const struct stat *sb,

View File

@ -45,6 +45,8 @@
E(ERR_THRD) /* Generic pthread error */ \
\
E(ERR_LIBEVENT) /* There are some problem with a libevent function */ \
\
E(ERR_SHOULD_EXIT) /* Probably got a C-c, program should exit now */ \
E(_ERR_COUNT) \

7
src/globals.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef _GLOBALS_H
#define _GLOBALS_H
#include <stdbool.h>
extern bool should_exit;
#endif /* _GLOBALS_H */

View File

@ -248,7 +248,11 @@ ssize_t net_send(const void *msg, size_t msg_len)
{
ssize_t w_len = send(net_socket, msg, msg_len, 0);
if (w_len == -1) {
uio_error("{net} Send failed: %s", strerror(errno));
int en = errno;
uio_error("{net} Send failed: %s", strerror(en));
if (en == EINTR)
return -2;
return -1;
}
return w_len;
@ -258,8 +262,14 @@ ssize_t net_read(void* out_data, size_t read_size)
{
ssize_t read = recv(net_socket, out_data, read_size, 0);
if (read == -1) {
int en = errno;
uio_error("{net} Read failed: %s", strerror(errno));
if (en == EINTR)
return -2;
return -1;
}
if (read == read_size)
uio_warning("{net} Data may have been discarded!");
return read;
}

View File

@ -12,6 +12,8 @@ enum error net_init();
/*
* Send and read data to and from the api
* Returns the number of bytes sent/read or -1 on error
* If the error is EINTR, it returns -2
*/
ssize_t net_send(const void *msg, size_t msg_len);
ssize_t net_read(void *out_data, size_t read_size);