2 * Copyright (C) 2013-2018 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. */
58 struct sockaddr
*addr
;
65 static pthread_key_t threadlocal_key
;
68 free_threadlocal (void *threadlocalv
)
70 struct threadlocal
*threadlocal
= threadlocalv
;
72 free (threadlocal
->name
);
73 free (threadlocal
->addr
);
74 free (threadlocal
->buffer
);
79 threadlocal_init (void)
83 err
= pthread_key_create (&threadlocal_key
, free_threadlocal
);
85 fprintf (stderr
, "%s: pthread_key_create: %s\n",
86 program_name
, strerror (err
));
92 threadlocal_new_server_thread (void)
94 struct threadlocal
*threadlocal
;
97 threadlocal
= calloc (1, sizeof *threadlocal
);
98 if (threadlocal
== NULL
) {
102 err
= pthread_setspecific (threadlocal_key
, threadlocal
);
105 perror ("pthread_setspecific");
111 threadlocal_set_name (const char *name
)
113 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
115 /* Copy name, as the original may be residing in a module, but we
116 * want our thread name to persist even after unload. */
118 free (threadlocal
->name
);
119 threadlocal
->name
= strdup (name
);
120 /* Best effort; logging a NULL name is better than exiting. */
121 if (threadlocal
->name
== NULL
)
127 threadlocal_set_instance_num (size_t instance_num
)
129 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
132 threadlocal
->instance_num
= instance_num
;
136 threadlocal_set_sockaddr (const struct sockaddr
*addr
, socklen_t addrlen
)
138 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
141 free (threadlocal
->addr
);
142 threadlocal
->addr
= calloc (1, addrlen
);
143 if (threadlocal
->addr
== NULL
) {
147 memcpy (threadlocal
->addr
, addr
, addrlen
);
152 threadlocal_get_name (void)
154 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
159 return threadlocal
->name
;
163 threadlocal_get_instance_num (void)
165 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
170 return threadlocal
->instance_num
;
174 threadlocal_set_error (int err
)
176 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
179 threadlocal
->err
= err
;
184 /* This preserves errno, for convenience.
187 threadlocal_get_error (void)
190 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
193 return threadlocal
? threadlocal
->err
: 0;
196 /* Return the single pread/pwrite buffer for this thread. The buffer
197 * size is increased to ‘size’ bytes if required.
199 * The buffer starts out as zeroes but after use may contain data from
200 * previous requests. This is fine because: (a) Correctly written
201 * plugins should overwrite the whole buffer on each request so no
202 * leak should occur. (b) The aim of this buffer is to avoid leaking
203 * random heap data from the core server; previous request data from
204 * the plugin is not considered sensitive.
207 threadlocal_buffer (size_t size
)
209 struct threadlocal
*threadlocal
= pthread_getspecific (threadlocal_key
);
214 if (threadlocal
->buffer_size
< size
) {
217 ptr
= realloc (threadlocal
->buffer
, size
);
219 nbdkit_error ("threadlocal_buffer: realloc: %m");
222 memset (ptr
, 0, size
);
223 threadlocal
->buffer
= ptr
;
224 threadlocal
->buffer_size
= size
;
227 return threadlocal
->buffer
;