We can't guarantee what storage duration the caller's request
for a thread name has; and in fact, if the caller uses
plugin_name() for their thread name, then the moment .unload
is called, our threadlocal storage is pointing to la-la-land
and we get a nice SEGV while trying to print any debug message.
So copy the user's string instead.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
src/threadlocal.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/src/threadlocal.c b/src/threadlocal.c
index d6e3942..24c381d 100644
--- a/src/threadlocal.c
+++ b/src/threadlocal.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2013 Red Hat Inc.
+ * Copyright (C) 2013-2017 Red Hat Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,7 @@
*/
struct threadlocal {
- const char *name; /* Can be NULL. */
+ char *name; /* Can be NULL. */
size_t instance_num; /* Can be 0. */
struct sockaddr *addr;
socklen_t addrlen;
@@ -69,6 +69,7 @@ free_threadlocal (void *threadlocalv)
{
struct threadlocal *threadlocal = threadlocalv;
+ free (threadlocal->name);
free (threadlocal->addr);
free (threadlocal);
}
@@ -104,8 +105,16 @@ threadlocal_set_name (const char *name)
{
struct threadlocal *threadlocal = pthread_getspecific (threadlocal_key);
- if (threadlocal)
- threadlocal->name = name;
+ /* Copy name, as the original may be residing in a module, but we
+ * want our thread name to persist even after unload. */
+ if (threadlocal) {
+ free (threadlocal->name);
+ threadlocal->name = strdup (name);
+ if (threadlocal->name == NULL) {
+ perror ("malloc");
+ exit (EXIT_FAILURE);
+ }
+ }
}
void
--
2.13.6