Skip to content

Commit

Permalink
iiod: Re-create IIO context when receiving USR1 signal
Browse files Browse the repository at this point in the history
Handle USR1 as a signal that IIOD should re-create the IIO context.
This allows support for hot-plugging IIO devices at runtime; the USR1
signal can then be sent from a udev script, for instance.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
  • Loading branch information
pcercuei committed Jun 5, 2023
1 parent f5f8422 commit 1753dbc
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 42 deletions.
92 changes: 69 additions & 23 deletions iiod/iiod.c
Expand Up @@ -37,6 +37,11 @@
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)

static int start_iiod(const char *uri, const char *ffs_mountpoint,
const char *uart_params, bool debug, bool interactive,
bool use_aio, uint16_t port, unsigned int nb_pipes,
int ep0_fd);

struct client_data {
int fd;
bool debug;
Expand Down Expand Up @@ -131,6 +136,14 @@ static void sig_handler(int sig)
thread_pool_stop(main_thread_pool);
}

static bool restart_usr1;

static void sig_handler_usr1(int sig)
{
restart_usr1 = true;
thread_pool_stop(main_thread_pool);
}

static int main_interactive(struct iio_context *ctx, bool verbose, bool use_aio,
const void *xml_zstd, size_t xml_zstd_len)
{
Expand Down Expand Up @@ -376,15 +389,12 @@ int main(int argc, char **argv)
long nb_pipes = 3, val;
char *end;
const char *arg = "local:";
struct iio_context *ctx;
int c, option_index = 0;
char *ffs_mountpoint = NULL;
char *uart_params = NULL;
char err_str[1024];
void *xml_zstd;
size_t xml_zstd_len = 0;
uint16_t port = IIOD_PORT;
int ret;
int ret, ep0_fd = 0;

while ((c = getopt_long(argc, argv, "+hVdDiaF:n:s:p:u:",
options, &option_index)) != -1) {
Expand Down Expand Up @@ -459,40 +469,79 @@ int main(int argc, char **argv)
}
}

ctx = iio_create_context_from_uri(arg);

if (!ctx) {
main_thread_pool = thread_pool_new();
if (!main_thread_pool) {
iio_strerror(errno, err_str, sizeof(err_str));
IIO_ERROR("Unable to create local context: %s\n", err_str);
IIO_ERROR("Unable to create thread pool: %s\n", err_str);
return EXIT_FAILURE;
}

xml_zstd = get_xml_zstd_data(ctx, &xml_zstd_len);
if (WITH_IIOD_USBD && ffs_mountpoint) {
ret = init_usb_daemon(ffs_mountpoint, nb_pipes);
if (ret < 0) {
iio_strerror(errno, err_str, sizeof(err_str));
IIO_ERROR("Unable to init USB: %s\n", err_str);

main_thread_pool = thread_pool_new();
if (!main_thread_pool) {
iio_strerror(errno, err_str, sizeof(err_str));
IIO_ERROR("Unable to create thread pool: %s\n", err_str);
ret = EXIT_FAILURE;
goto out_destroy_context;
thread_pool_destroy(main_thread_pool);
return EXIT_FAILURE;
}

ep0_fd = ret;
}

set_handler(SIGHUP, sig_handler);
set_handler(SIGPIPE, sig_handler);
set_handler(SIGINT, sig_handler);
set_handler(SIGTERM, sig_handler);
set_handler(SIGUSR1, sig_handler_usr1);

do {
thread_pool_restart(main_thread_pool);
restart_usr1 = false;

ret = start_iiod(arg, ffs_mountpoint, uart_params, debug,
interactive, use_aio, port, nb_pipes, ep0_fd);
} while (!ret && restart_usr1);

thread_pool_destroy(main_thread_pool);

if (WITH_IIOD_USBD && ffs_mountpoint)
close(ep0_fd);

return ret;
}

static int start_iiod(const char *uri, const char *ffs_mountpoint,
const char *uart_params, bool debug, bool interactive,
bool use_aio, uint16_t port, unsigned int nb_pipes,
int ep0_fd)
{
struct iio_context *ctx;
char err_str[1024];
void *xml_zstd;
size_t xml_zstd_len = 0;
int ret;

ctx = iio_create_context_from_uri(uri);
if (!ctx) {
iio_strerror(errno, err_str, sizeof(err_str));
IIO_ERROR("Unable to create local context: %s\n", err_str);
return EXIT_FAILURE;
}

xml_zstd = get_xml_zstd_data(ctx, &xml_zstd_len);

if (WITH_IIOD_USBD && ffs_mountpoint) {
/* We pass use_aio == true directly, this is ensured to be true
* by the CMake script. */
ret = start_usb_daemon(ctx, ffs_mountpoint,
debug, true, (unsigned int) nb_pipes,
debug, true, (unsigned int) nb_pipes, ep0_fd,
main_thread_pool, xml_zstd, xml_zstd_len);
if (ret) {
iio_strerror(-ret, err_str, sizeof(err_str));
IIO_ERROR("Unable to start USB daemon: %s\n", err_str);
ret = EXIT_FAILURE;
goto out_destroy_thread_pool;
goto out_free_xml_data;
}
}

Expand All @@ -504,7 +553,7 @@ int main(int argc, char **argv)
iio_strerror(-ret, err_str, sizeof(err_str));
IIO_ERROR("Unable to start serial daemon: %s\n", err_str);
ret = EXIT_FAILURE;
goto out_destroy_thread_pool;
goto out_thread_pool_stop;
}
}

Expand All @@ -513,16 +562,13 @@ int main(int argc, char **argv)
else
ret = main_server(ctx, debug, xml_zstd, xml_zstd_len, port);

out_thread_pool_stop:
/*
* In case we got here through an error in the main thread make sure all
* the worker threads are signaled to shutdown.
*/

out_destroy_thread_pool:
thread_pool_stop_and_wait(main_thread_pool);
thread_pool_destroy(main_thread_pool);

out_destroy_context:
out_free_xml_data:
free(xml_zstd);
iio_context_destroy(ctx);

Expand Down
3 changes: 2 additions & 1 deletion iiod/ops.h
Expand Up @@ -92,9 +92,10 @@ void interpreter(struct iio_context *ctx, int fd_in, int fd_out, bool verbose,
bool is_socket, bool is_usb, bool use_aio, struct thread_pool *pool,
const void *xml_zstd, size_t xml_zstd_len);

int init_usb_daemon(const char *ffs, unsigned int nb_pipes);
int start_usb_daemon(struct iio_context *ctx, const char *ffs,
bool debug, bool use_aio, unsigned int nb_pipes,
struct thread_pool *pool,
int ep0_fd, struct thread_pool *pool,
const void *xml_zstd, size_t xml_zstd_len);
int start_serial_daemon(struct iio_context *ctx, const char *uart_params,
bool debug, struct thread_pool *pool,
Expand Down
41 changes: 23 additions & 18 deletions iiod/usbd.c
Expand Up @@ -217,7 +217,6 @@ static void usbd_main(struct thread_pool *pool, void *d)
thread_pool_destroy(pdata->pool[i]);
}

close(pdata->ep0_fd);
free(pdata->ffs);
free(pdata->pool);
free(pdata);
Expand Down Expand Up @@ -328,14 +327,34 @@ static int write_header(int fd, unsigned int nb_pipes)
return 0;
}

int init_usb_daemon(const char *ffs, unsigned int nb_pipes)
{
char buf[256];
int ep0_fd, ret;

snprintf(buf, sizeof(buf), "%s/ep0", ffs);

ep0_fd = open(buf, O_RDWR);
if (ep0_fd < 0) {
return -errno;
}

ret = write_header(ep0_fd, nb_pipes);
if (ret < 0) {
close(ep0_fd);
return ret;
}

return ep0_fd;
}

int start_usb_daemon(struct iio_context *ctx, const char *ffs,
bool debug, bool use_aio, unsigned int nb_pipes,
struct thread_pool *pool,
int ep0_fd, struct thread_pool *pool,
const void *xml_zstd, size_t xml_zstd_len)
{
struct usbd_pdata *pdata;
unsigned int i;
char buf[256];
int ret;

pdata = zalloc(sizeof(*pdata));
Expand All @@ -356,18 +375,6 @@ int start_usb_daemon(struct iio_context *ctx, const char *ffs,
goto err_free_pdata_pool;
}

snprintf(buf, sizeof(buf), "%s/ep0", ffs);

pdata->ep0_fd = open(buf, O_RDWR);
if (pdata->ep0_fd < 0) {
ret = -errno;
goto err_free_ffs;
}

ret = write_header(pdata->ep0_fd, nb_pipes);
if (ret < 0)
goto err_close_ep0;

for (i = 0; i < nb_pipes; i++) {
pdata->pool[i] = thread_pool_new();
if (!pdata->pool[i]) {
Expand All @@ -381,6 +388,7 @@ int start_usb_daemon(struct iio_context *ctx, const char *ffs,
pdata->use_aio = use_aio;
pdata->xml_zstd = xml_zstd;
pdata->xml_zstd_len = xml_zstd_len;
pdata->ep0_fd = ep0_fd;

ret = thread_pool_add_thread(pool, usbd_main, pdata, "usbd_main_thd");
if (!ret)
Expand All @@ -393,9 +401,6 @@ int start_usb_daemon(struct iio_context *ctx, const char *ffs,
if (pdata->pool[i])
thread_pool_destroy(pdata->pool[i]);
}
err_close_ep0:
close(pdata->ep0_fd);
err_free_ffs:
free(pdata->ffs);
err_free_pdata_pool:
free(pdata->pool);
Expand Down

0 comments on commit 1753dbc

Please sign in to comment.