From b5f194fa4ad6a496babd1aa5fac5d8b5a1f06829 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Thu, 16 Nov 2017 14:54:57 -0600 Subject: [PATCH] threadlocal: Copy thread name 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. Make the update best-effort, since we may be creating a new thread while an existing connection is already in service. If strdup fails, we'll mention the failure, but it's better to still keep the program running with no thread name than to die [of course, if strdup fails, we'll probably face other failures quite soon]. Signed-off-by: Eric Blake --- src/threadlocal.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/threadlocal.c b/src/threadlocal.c index d6e3942c..267f3488 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,15 @@ 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); + /* Best effort; logging a NULL name is better than exiting. */ + if (threadlocal->name == NULL) + perror ("malloc"); + } } void -- 2.11.4.GIT