2 * Copyright (C) 2013-2019 Red Hat Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of Red Hat nor the names of its contributors may be
16 * used to endorse or promote products derived from this software without
17 * specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 /* Note that most thread-local storage data is informational, used for
47 * smart error and debug messages on the server side. However, error
48 * tracking can be used to influence which error is sent to the client
51 * The main thread does not have any associated Thread Local Storage,
52 * *unless* it is serving a request (the '-s' option).
56 char *name
; /* Can be NULL. */
57 size_t instance_num
; /* Can be 0. */
61 struct connection
*conn
;
64 static pthread_key_t threadlocal_key
;
67 free_threadlocal (void *threadlocalv
)
69 struct threadlocal
*threadlocal
= threadlocalv
;
71 free (threadlocal
->name
);
72 free (threadlocal
->buffer
);
77 threadlocal_init (void)
81 err
= pthread_key_create (&threadlocal_key
, free_threadlocal
);
83 fprintf (stderr
, "%s: pthread_key_create: %s\n",
84 program_name
, strerror (err
));
90 threadlocal_new_server_thread (void)
92 struct threadlocal
*threadlocal
;
95 threadlocal
= calloc (1, sizeof *threadlocal
);
96 if (threadlocal
== NULL
) {
100 err
= pthread_setspecific (threadlocal_key
, threadlocal
);
103 perror ("pthread_setspecific");
109 threadlocal_set_name (const char *name
)
111 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
113 /* Copy name, as the original may be residing in a module, but we
114 * want our thread name to persist even after unload. */
116 free (threadlocal
->name
);
117 threadlocal
->name
= strdup (name
);
118 /* Best effort; logging a NULL name is better than exiting. */
119 if (threadlocal
->name
== NULL
)
125 threadlocal_set_instance_num (size_t instance_num
)
127 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
130 threadlocal
->instance_num
= instance_num
;
134 threadlocal_get_name (void)
136 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
141 return threadlocal
->name
;
145 threadlocal_get_instance_num (void)
147 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
152 return threadlocal
->instance_num
;
156 threadlocal_set_error (int err
)
158 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
161 threadlocal
->err
= err
;
166 /* This preserves errno, for convenience.
169 threadlocal_get_error (void)
172 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
175 return threadlocal
? threadlocal
->err
: 0;
178 /* Return the single pread/pwrite buffer for this thread. The buffer
179 * size is increased to ‘size’ bytes if required.
181 * The buffer starts out as zeroes but after use may contain data from
182 * previous requests. This is fine because: (a) Correctly written
183 * plugins should overwrite the whole buffer on each request so no
184 * leak should occur. (b) The aim of this buffer is to avoid leaking
185 * random heap data from the core server; previous request data from
186 * the plugin is not considered sensitive.
189 threadlocal_buffer (size_t size
)
191 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
196 if (threadlocal
->buffer_size
< size
) {
199 ptr
= realloc (threadlocal
->buffer
, size
);
201 nbdkit_error ("threadlocal_buffer: realloc: %m");
204 memset (ptr
, 0, size
);
205 threadlocal
->buffer
= ptr
;
206 threadlocal
->buffer_size
= size
;
209 return threadlocal
->buffer
;
212 /* Set (or clear) the connection that is using the current thread */
214 threadlocal_set_conn (struct connection
*conn
)
216 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
219 threadlocal
->conn
= conn
;
222 /* Get the connection associated with this thread, if available */
224 threadlocal_get_conn (void)
226 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
228 return threadlocal
? threadlocal
->conn
: NULL
;