Bug Summary

File:lib/lwan.c
Warning:line 340, column 17
Potential leak of memory pointed to by 'key_copy'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lwan.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -fno-plt -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/lib -resource-dir /usr/lib/clang/17 -include /home/buildbot/lwan-worker/clang-analyze/build/lwan-build-config.h -D _FILE_OFFSET_BITS=64 -D _TIME_BITS=64 -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib/missing -I /home/buildbot/lwan-worker/clang-analyze/build -I /usr/include/luajit-2.1 -I /usr/include/valgrind -I /home/buildbot/lwan-worker/clang-analyze/build/src/lib -internal-isystem /usr/lib/clang/17/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../x86_64-pc-linux-gnu/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-override-init -Wno-unused-parameter -Wno-free-nonheap-object -std=gnu11 -fdebug-compilation-dir=/home/buildbot/lwan-worker/clang-analyze/build/src/lib -ferror-limit 19 -stack-protector 2 -fgnuc-version=4.2.1 -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/buildbot/lwan-worker/clang-analyze/CLANG/2024-04-14-032020-1719870-1 -x c /home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c
1/*
2 * lwan - web server
3 * Copyright (c) 2012, 2013 L. A. F. Pereira <l@tia.mat.br>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 * USA.
19 */
20
21#define _GNU_SOURCE
22#include <assert.h>
23#include <ctype.h>
24#include <dlfcn.h>
25#include <errno(*__errno_location ()).h>
26#include <fcntl.h>
27#include <libproc.h>
28#include <limits.h>
29#include <signal.h>
30#include <stdlib.h>
31#include <string.h>
32#include <sys/resource.h>
33#include <sys/socket.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37#include "lwan-private.h"
38
39#include "lwan-config.h"
40#include "lwan-http-authorize.h"
41
42#if defined(LWAN_HAVE_LUA)
43#include "lwan-lua.h"
44#endif
45
46/* Ideally, this would check if all items in enum lwan_request_flags,
47 * when bitwise-or'd together, would not have have any bit set that
48 * is also set in REQUEST_METHOD_MASK. */
49static_assert_Static_assert(REQUEST_ACCEPT_DEFLATE > REQUEST_METHOD_MASK,
50 "enough bits to store request methods");
51
52/* See detect_fastest_monotonic_clock() */
53clockid_t monotonic_clock_id = CLOCK_MONOTONIC1;
54
55static const struct lwan_config default_config = {
56 .listener = "localhost:8080",
57 .keep_alive_timeout = 15,
58 .quiet = false0,
59 .proxy_protocol = false0,
60 .allow_cors = false0,
61 .expires = 1 * ONE_WEEK(((60 * 60) * 24) * 7),
62 .n_threads = 0,
63 .request_buffer_size = DEFAULT_BUFFER_SIZE4096,
64 .max_post_data_size = 10 * DEFAULT_BUFFER_SIZE4096,
65 .allow_post_temp_file = false0,
66 .max_put_data_size = 10 * DEFAULT_BUFFER_SIZE4096,
67 .allow_put_temp_file = false0,
68 .use_dynamic_buffer = false0,
69};
70
71LWAN_HANDLER_ROUTE(brew_coffee, NULL /* do not autodetect this route */)static enum lwan_http_status lwan_handler_brew_coffee( struct
lwan_request *, struct lwan_response *, void *); static const
struct lwan_handler_info __attribute__((used, section("lwan_handler"
))) __attribute__((aligned(8))) lwan_handler_info_brew_coffee
= { .name = "brew_coffee", .route = ((void*)0), .handler = lwan_handler_brew_coffee
, }; __attribute__((used)) static enum lwan_http_status lwan_handler_brew_coffee
( struct lwan_request *request __attribute__((unused)), struct
lwan_response *response __attribute__((unused)), void *data __attribute__
((unused)))
72{
73 /* Placeholder handler so that __start_lwan_handler and __stop_lwan_handler
74 * symbols will get defined.
75 */
76 return HTTP_I_AM_A_TEAPOT;
77}
78
79__attribute__((no_sanitize_address))
80static void *find_handler(const char *name)
81{
82 const struct lwan_handler_info *handler;
83
84 LWAN_SECTION_FOREACH(lwan_handler, handler)for (handler = ({ extern const typeof(*handler) __start_lwan_handler
[]; __start_lwan_handler; }); handler < ({ extern const typeof
(*handler) __stop_lwan_handler[]; __stop_lwan_handler; }); (handler
)++)
{
85 if (streq(handler->name, name))
86 return handler->handler;
87 }
88
89 return NULL((void*)0);
90}
91
92__attribute__((no_sanitize_address))
93static const struct lwan_module *find_module(const char *name)
94{
95 const struct lwan_module_info *module;
96
97 LWAN_SECTION_FOREACH(lwan_module, module)for (module = ({ extern const typeof(*module) __start_lwan_module
[]; __start_lwan_module; }); module < ({ extern const typeof
(*module) __stop_lwan_module[]; __stop_lwan_module; }); (module
)++)
{
98 if (streq(module->name, name))
99 return module->module;
100 }
101
102 return NULL((void*)0);
103}
104
105static void destroy_urlmap(void *data)
106{
107 struct lwan_url_map *url_map = data;
108
109 if (url_map->module) {
110 const struct lwan_module *module = url_map->module;
111
112 if (module->destroy)
113 module->destroy(url_map->data);
114 } else if (url_map->data && url_map->flags & HANDLER_DATA_IS_HASH_TABLE) {
115 hash_free(url_map->data);
116 }
117
118 free(url_map->authorization.realm);
119 free(url_map->authorization.password_file);
120 free((char *)url_map->prefix);
121 free(url_map);
122}
123
124static struct lwan_url_map *add_url_map(struct lwan_trie *t, const char *prefix,
125 const struct lwan_url_map *map)
126{
127 struct lwan_url_map *copy = malloc(sizeof(*copy));
128
129 if (!copy)
130 lwan_status_critical_perror("Could not copy URL map")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 130, __FUNCTION__, "Could not copy URL map")
;
131
132 memcpy(copy, map, sizeof(*copy));
133
134 copy->prefix = strdup(prefix ? prefix : copy->prefix);
135 if (!copy->prefix)
136 lwan_status_critical_perror("Could not copy URL prefix")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 136, __FUNCTION__, "Could not copy URL prefix")
;
137
138 copy->prefix_len = strlen(copy->prefix);
139 lwan_trie_add(t, copy->prefix, copy);
140
141 return copy;
142}
143
144static bool_Bool can_override_header(const char *name)
145{
146 /* NOTE: Update lwan_prepare_response_header_full() in lwan-response.c
147 * if new headers are added here. */
148
149 if (strcaseequal_neutral(name, "Date"))
150 return false0;
151 if (strcaseequal_neutral(name, "Expires"))
152 return false0;
153 if (strcaseequal_neutral(name, "WWW-Authenticate"))
154 return false0;
155 if (strcaseequal_neutral(name, "Connection"))
156 return false0;
157 if (strcaseequal_neutral(name, "Content-Type"))
158 return false0;
159 if (strcaseequal_neutral(name, "Transfer-Encoding"))
160 return false0;
161 if (strcaseequal_neutral_len(name, "Access-Control-Allow-",
162 sizeof("Access-Control-Allow-") - 1))
163 return false0;
164
165 return true1;
166}
167
168static void build_response_headers(struct lwan *l,
169 const struct lwan_key_value *kv)
170{
171 struct lwan_strbuf strbuf;
172 bool_Bool set_server = false0;
173
174 assert(l)((void) sizeof ((l) ? 1 : 0), __extension__ ({ if (l) ; else __assert_fail
("l", "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 174, __extension__ __PRETTY_FUNCTION__); }))
;
175
176 lwan_strbuf_init(&strbuf);
177
178 for (; kv && kv->key; kv++) {
179 if (!can_override_header(kv->key)) {
180 lwan_status_warning("Cannot override header '%s'", kv->key)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 180, __FUNCTION__, "Cannot override header '%s'", kv->key
)
;
181 } else {
182 if (strcaseequal_neutral(kv->key, "Server"))
183 set_server = true1;
184
185 lwan_strbuf_append_printf(&strbuf, "\r\n%s: %s", kv->key,
186 kv->value);
187 }
188 }
189
190 if (!set_server)
191 lwan_strbuf_append_strz(&strbuf, "\r\nServer: lwan");
192
193 lwan_strbuf_append_strz(&strbuf, "\r\n\r\n");
194
195 l->headers = (struct lwan_value){.value = lwan_strbuf_get_buffer(&strbuf),
196 .len = lwan_strbuf_get_length(&strbuf)};
197}
198
199static void parse_global_headers(struct config *c,
200 struct lwan *lwan)
201{
202 struct lwan_key_value_array hdrs;
203 const struct config_line *l;
204 struct lwan_key_value *kv;
205
206 lwan_key_value_array_init(&hdrs);
207
208 while ((l = config_read_line(c))) {
209 switch (l->type) {
210 case CONFIG_LINE_TYPE_SECTION:
211 config_error(
212 c, "No sections are supported under the 'headers' section");
213 goto cleanup;
214
215 case CONFIG_LINE_TYPE_LINE:
216 kv = lwan_key_value_array_append(&hdrs);
217 if (!kv) {
218 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 219, __FUNCTION__, "Could not allocate memory for custom response header"
)
219 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 219, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
220 }
221
222 kv->key = strdup(l->key);
223 if (!kv->key) {
224 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 225, __FUNCTION__, "Could not allocate memory for custom response header"
)
225 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 225, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
226 }
227
228 kv->value = strdup(l->value);
229 if (!kv->value) {
230 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 231, __FUNCTION__, "Could not allocate memory for custom response header"
)
231 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 231, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
232 }
233 break;
234
235 case CONFIG_LINE_TYPE_SECTION_END:
236 kv = lwan_key_value_array_append(&hdrs);
237 if (!kv) {
238 lwan_status_critical_perror(lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 239, __FUNCTION__, "Could not allocate memory for custom response header"
)
239 "Could not allocate memory for custom response header")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 239, __FUNCTION__, "Could not allocate memory for custom response header"
)
;
240 }
241
242 kv->key = NULL((void*)0);
243 kv->value = NULL((void*)0);
244
245 build_response_headers(lwan, lwan_key_value_array_get_array(&hdrs));
246 goto cleanup;
247 }
248 }
249
250 config_error(c, "EOF while looking for end of 'headers' section");
251
252cleanup:
253 LWAN_ARRAY_FOREACH (&hdrs, kv)for (kv = (&hdrs)->base.base; kv < ((typeof(kv))(&
hdrs)->base.base + (&hdrs)->base.elements); kv++)
{
254 free(kv->key);
255 free(kv->value);
256 }
257 lwan_key_value_array_reset(&hdrs);
258}
259
260static void parse_listener_prefix_authorization(struct config *c,
261 const struct config_line *l,
262 struct lwan_url_map *url_map)
263{
264 if (!streq(l->value, "basic")) {
265 config_error(c, "Only basic authorization supported");
266 return;
267 }
268
269 memset(&url_map->authorization, 0, sizeof(url_map->authorization));
270
271 while ((l = config_read_line(c))) {
272 switch (l->type) {
273 case CONFIG_LINE_TYPE_LINE:
274 if (streq(l->key, "realm")) {
275 free(url_map->authorization.realm);
276 url_map->authorization.realm = strdup(l->value);
277 } else if (streq(l->key, "password_file")) {
278 free(url_map->authorization.password_file);
279 url_map->authorization.password_file = realpath(l->value, NULL((void*)0));
280 if (!url_map->authorization.password_file)
281 config_error(c, "Could not determine full path for password file: %s", l->value);
282 }
283 break;
284
285 case CONFIG_LINE_TYPE_SECTION:
286 config_error(c, "Unexpected section: %s", l->key);
287 goto error;
288
289 case CONFIG_LINE_TYPE_SECTION_END:
290 if (!url_map->authorization.realm)
291 url_map->authorization.realm = strdup("Lwan");
292 if (!url_map->authorization.password_file)
293 url_map->authorization.password_file = strdup("htpasswd");
294
295 url_map->flags |= HANDLER_MUST_AUTHORIZE;
296 return;
297 }
298 }
299
300 config_error(c, "Could not find end of authorization section");
301
302error:
303 free(url_map->authorization.realm);
304 free(url_map->authorization.password_file);
305}
306
307__attribute__((no_sanitize_address))
308static const char *get_module_name(const struct lwan_module *module)
309{
310 const struct lwan_module_info *iter;
311
312 LWAN_SECTION_FOREACH(lwan_module, iter)for (iter = ({ extern const typeof(*iter) __start_lwan_module
[]; __start_lwan_module; }); iter < ({ extern const typeof
(*iter) __stop_lwan_module[]; __stop_lwan_module; }); (iter)++
)
{
313 if (iter->module == module)
314 return iter->name;
315 }
316
317 return "<unknown>";
318}
319
320static void parse_listener_prefix(struct config *c,
321 const struct config_line *l,
322 struct lwan *lwan,
323 const struct lwan_module *module,
324 void *handler)
325{
326 struct lwan_url_map url_map = {};
327 struct hash *hash = hash_str_new(free, free);
328 char *prefix = strdupa(l->value)(__extension__ ({ const char *__old = (l->value); size_t __len
= strlen (__old) + 1; char *__new = (char *) __builtin_alloca
(__len); (char *) memcpy (__new, __old, __len); }))
;
329 struct config *isolated;
330
331 if (!hash)
21
Assuming 'hash' is non-null
22
Taking false branch
332 lwan_status_critical("Could not allocate hash table")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 332, __FUNCTION__, "Could not allocate hash table")
;
333
334 isolated = config_isolate_section(c, l);
335 if (!isolated) {
23
Assuming 'isolated' is non-null
24
Taking false branch
336 config_error(c, "Could not isolate configuration file");
337 goto out;
338 }
339
340 while ((l = config_read_line(c))) {
25
Loop condition is true. Entering loop body
32
Execution continues on line 340
33
Potential leak of memory pointed to by 'key_copy'
341 switch (l->type) {
26
Control jumps to 'case CONFIG_LINE_TYPE_LINE:' at line 342
342 case CONFIG_LINE_TYPE_LINE: {
343 char *key_copy = strdup(l->key);
27
Memory is allocated
344 char *value_copy = strdup(l->value);
345
346 if (!key_copy)
28
Assuming 'key_copy' is non-null
29
Taking false branch
347 lwan_status_critical("Could not copy key from config file")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 347, __FUNCTION__, "Could not copy key from config file")
;
348 if (!value_copy)
30
Assuming 'value_copy' is non-null
31
Taking false branch
349 lwan_status_critical("Could not copy value from config file")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 349, __FUNCTION__, "Could not copy value from config file")
;
350
351 hash_add(hash, key_copy, value_copy);
352 break;
353 }
354
355 case CONFIG_LINE_TYPE_SECTION:
356 if (streq(l->key, "authorization")) {
357 parse_listener_prefix_authorization(c, l, &url_map);
358 } else if (!config_skip_section(c, l)) {
359 config_error(c, "Could not skip section");
360 goto out;
361 }
362 break;
363
364 case CONFIG_LINE_TYPE_SECTION_END:
365 goto add_map;
366 }
367 }
368
369 config_error(c, "Expecting section end while parsing prefix");
370 goto out;
371
372add_map:
373 assert((handler && !module) || (!handler && module))((void) sizeof (((handler && !module) || (!handler &&
module)) ? 1 : 0), __extension__ ({ if ((handler && !
module) || (!handler && module)) ; else __assert_fail
("(handler && !module) || (!handler && module)"
, "/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 373, __extension__ __PRETTY_FUNCTION__); }))
;
374
375 if (handler) {
376 url_map.handler = handler;
377 url_map.flags |= HANDLER_PARSE_MASK | HANDLER_DATA_IS_HASH_TABLE;
378 url_map.data = hash;
379 url_map.module = NULL((void*)0);
380
381 hash = NULL((void*)0);
382 } else if (module->create_from_hash && module->handle_request) {
383 lwan_status_debug("Initializing module %s from config",lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 384, __FUNCTION__, "Initializing module %s from config", get_module_name
(module))
384 get_module_name(module))lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 384, __FUNCTION__, "Initializing module %s from config", get_module_name
(module))
;
385
386 url_map.data = module->create_from_hash(prefix, hash);
387 if (!url_map.data) {
388 config_error(c, "Could not create module instance");
389 goto out;
390 }
391
392 if (module->parse_conf && !module->parse_conf(url_map.data, isolated)) {
393 const char *msg = config_last_error(isolated);
394
395 config_error(c, "Error from module: %s", msg ? msg : "Unknown");
396 goto out;
397 }
398
399 url_map.handler = module->handle_request;
400 url_map.flags |= module->flags;
401 url_map.module = module;
402 } else if (UNLIKELY(!module->create_from_hash)__builtin_expect(((!module->create_from_hash)), (0))) {
403 config_error(c, "Module isn't prepared to load settings from a file; "
404 "create_from_hash() method isn't present");
405 goto out;
406 } else if (UNLIKELY(!module->handle_request)__builtin_expect(((!module->handle_request)), (0))) {
407 config_error(c, "Module does not have handle_request() method");
408 goto out;
409 }
410
411 add_url_map(&lwan->url_map_trie, prefix, &url_map);
412
413out:
414 hash_free(hash);
415 config_close(isolated);
416}
417
418static void register_url_map(struct lwan *l, const struct lwan_url_map *map)
419{
420 struct lwan_url_map *copy = add_url_map(&l->url_map_trie, NULL((void*)0), map);
421
422 if (copy->module && copy->module->create) {
423 lwan_status_debug("Initializing module %s from struct",lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 424, __FUNCTION__, "Initializing module %s from struct", get_module_name
(copy->module))
424 get_module_name(copy->module))lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 424, __FUNCTION__, "Initializing module %s from struct", get_module_name
(copy->module))
;
425
426 copy->data = copy->module->create(map->prefix, copy->args);
427 if (!copy->data) {
428 lwan_status_critical("Could not initialize module %s",lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 429, __FUNCTION__, "Could not initialize module %s", get_module_name
(copy->module))
429 get_module_name(copy->module))lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 429, __FUNCTION__, "Could not initialize module %s", get_module_name
(copy->module))
;
430 }
431
432 copy->flags = copy->module->flags;
433 copy->handler = copy->module->handle_request;
434 } else {
435 copy->flags = HANDLER_PARSE_MASK;
436 }
437}
438
439void lwan_set_url_map(struct lwan *l, const struct lwan_url_map *map)
440{
441 lwan_trie_destroy(&l->url_map_trie);
442 if (UNLIKELY(!lwan_trie_init(&l->url_map_trie, destroy_urlmap))__builtin_expect(((!lwan_trie_init(&l->url_map_trie, destroy_urlmap
))), (0))
)
443 lwan_status_critical_perror("Could not initialize trie")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 443, __FUNCTION__, "Could not initialize trie")
;
444
445 for (; map->prefix; map++)
446 register_url_map(l, map);
447}
448
449__attribute__((no_sanitize_address))
450void lwan_detect_url_map(struct lwan *l)
451{
452 const struct lwan_handler_info *iter;
453
454 lwan_trie_destroy(&l->url_map_trie);
455 if (UNLIKELY(!lwan_trie_init(&l->url_map_trie, destroy_urlmap))__builtin_expect(((!lwan_trie_init(&l->url_map_trie, destroy_urlmap
))), (0))
)
456 lwan_status_critical_perror("Could not initialize trie")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 456, __FUNCTION__, "Could not initialize trie")
;
457
458 LWAN_SECTION_FOREACH(lwan_handler, iter)for (iter = ({ extern const typeof(*iter) __start_lwan_handler
[]; __start_lwan_handler; }); iter < ({ extern const typeof
(*iter) __stop_lwan_handler[]; __stop_lwan_handler; }); (iter
)++)
{
459 if (!iter->route)
460 continue;
461
462 lwan_status_debug("Using handler `%s' for route `%s'",lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 463, __FUNCTION__, "Using handler `%s' for route `%s'", iter
->name, iter->route)
463 iter->name, iter->route)lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 463, __FUNCTION__, "Using handler `%s' for route `%s'", iter
->name, iter->route)
;
464
465 const struct lwan_url_map map = {.prefix = iter->route,
466 .handler = iter->handler};
467 register_url_map(l, &map);
468 }
469}
470
471const char *lwan_get_config_path(char *path_buf, size_t path_buf_len)
472{
473 char buffer[PATH_MAX4096];
474
475 if (proc_pidpath(getpid(), buffer, sizeof(buffer)) < 0)
476 goto out;
477
478 char *path = strrchr(buffer, '/');
479 if (!path)
480 goto out;
481 int ret = snprintf(path_buf, path_buf_len, "%s.conf", path + 1);
482 if (ret < 0 || ret >= (int)path_buf_len)
483 goto out;
484
485 return path_buf;
486
487out:
488 return "lwan.conf";
489}
490
491static void parse_tls_listener(struct config *conf, const struct config_line *line, struct lwan *lwan)
492{
493#if !defined(LWAN_HAVE_MBEDTLS)
494 config_error(conf, "Lwan has been built without mbedTLS support");
495 return;
496#endif
497
498 lwan->config.tls_listener = strdup(line->value);
499 if (!lwan->config.tls_listener) {
500 config_error(conf, "Could not allocate memory for tls_listener");
501 return;
502 }
503
504 lwan->config.ssl.cert = NULL((void*)0);
505 lwan->config.ssl.key = NULL((void*)0);
506
507 while ((line = config_read_line(conf))) {
508 switch (line->type) {
509 case CONFIG_LINE_TYPE_SECTION_END:
510 if (!lwan->config.ssl.cert)
511 config_error(conf, "Missing path to certificate");
512 if (!lwan->config.ssl.key)
513 config_error(conf, "Missing path to private key");
514 return;
515 case CONFIG_LINE_TYPE_SECTION:
516 config_error(conf, "Unexpected section: %s", line->key);
517 return;
518 case CONFIG_LINE_TYPE_LINE:
519 if (streq(line->key, "cert")) {
520 free(lwan->config.ssl.cert);
521 lwan->config.ssl.cert = strdup(line->value);
522 if (!lwan->config.ssl.cert)
523 return lwan_status_critical("Could not copy string")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 523, __FUNCTION__, "Could not copy string")
;
524 } else if (streq(line->key, "key")) {
525 free(lwan->config.ssl.key);
526 lwan->config.ssl.key = strdup(line->value);
527 if (!lwan->config.ssl.key)
528 return lwan_status_critical("Could not copy string")lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 528, __FUNCTION__, "Could not copy string")
;
529 } else if (streq(line->key, "hsts")) {
530 lwan->config.ssl.send_hsts_header = parse_bool(line->value, false0);
531 } else {
532 config_error(conf, "Unexpected key: %s", line->key);
533 }
534 }
535 }
536
537 config_error(conf, "Expecting section end while parsing SSL configuration");
538}
539
540static void
541parse_listener(struct config *c, const struct config_line *l, struct lwan *lwan)
542{
543 lwan->config.listener = strdup(l->value);
544 if (!lwan->config.listener)
545 config_error(c, "Could not allocate memory for listener");
546
547 while ((l = config_read_line(c))) {
548 switch (l->type) {
549 case CONFIG_LINE_TYPE_LINE:
550 config_error(c, "Unexpected key %s", l->key);
551 return;
552 case CONFIG_LINE_TYPE_SECTION:
553 config_error(c, "Unexpected section %s", l->key);
554 return;
555 case CONFIG_LINE_TYPE_SECTION_END:
556 return;
557 }
558 }
559
560 config_error(c, "Unexpected EOF while parsing listener");
561}
562
563static void
564parse_site(struct config *c, const struct config_line *l, struct lwan *lwan)
565{
566 while ((l = config_read_line(c))) {
14
Loop condition is true. Entering loop body
567 switch (l->type) {
15
Control jumps to 'case CONFIG_LINE_TYPE_SECTION:' at line 571
568 case CONFIG_LINE_TYPE_LINE:
569 config_error(c, "Expecting prefix section");
570 return;
571 case CONFIG_LINE_TYPE_SECTION:
572 /* FIXME: per-site authorization? */
573
574 if (l->key[0] == '&') {
16
Assuming the condition is false
17
Taking false branch
575 void *handler = find_handler(l->key + 1);
576 if (handler) {
577 parse_listener_prefix(c, l, lwan, NULL((void*)0), handler);
578 continue;
579 }
580
581 config_error(c, "Could not find handler name: %s", l->key + 1);
582 return;
583 }
584
585 const struct lwan_module *module = find_module(l->key);
586 if (module) {
18
Assuming 'module' is non-null
19
Taking true branch
587 parse_listener_prefix(c, l, lwan, module, NULL((void*)0));
20
Calling 'parse_listener_prefix'
588 continue;
589 }
590
591 config_error(c, "Invalid section or module not found: %s", l->key);
592 return;
593 case CONFIG_LINE_TYPE_SECTION_END:
594 return;
595 }
596 }
597
598 config_error(c, "Expecting section end while parsing listener");
599}
600
601static bool_Bool setup_from_config(struct lwan *lwan, const char *path)
602{
603 const struct config_line *line;
604 struct config *conf;
605 bool_Bool has_site = false0;
606 bool_Bool has_listener = false0;
607 bool_Bool has_tls_listener = false0;
608 char path_buf[PATH_MAX4096];
609
610 if (!path
3.1
'path' is null
)
4
Taking true branch
611 path = lwan_get_config_path(path_buf, sizeof(path_buf));
612 lwan_status_info("Loading configuration file: %s", path)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 612, __FUNCTION__, "Loading configuration file: %s", path)
;
613
614 conf = config_open(path);
615 if (!conf)
5
Assuming 'conf' is non-null
6
Taking false branch
616 return false0;
617
618 if (!lwan_trie_init(&lwan->url_map_trie, destroy_urlmap))
7
Assuming the condition is false
8
Taking false branch
619 return false0;
620
621 while ((line = config_read_line(conf))) {
9
Loop condition is true. Entering loop body
622 switch (line->type) {
10
Control jumps to 'case CONFIG_LINE_TYPE_SECTION:' at line 709
623 case CONFIG_LINE_TYPE_LINE:
624 if (streq(line->key, "keep_alive_timeout")) {
625 lwan->config.keep_alive_timeout = (unsigned int)parse_long(
626 line->value, default_config.keep_alive_timeout);
627 } else if (streq(line->key, "quiet")) {
628 lwan->config.quiet =
629 parse_bool(line->value, default_config.quiet);
630 } else if (streq(line->key, "proxy_protocol")) {
631 lwan->config.proxy_protocol =
632 parse_bool(line->value, default_config.proxy_protocol);
633 } else if (streq(line->key, "allow_cors")) {
634 lwan->config.allow_cors =
635 parse_bool(line->value, default_config.allow_cors);
636 } else if (streq(line->key, "use_dynamic_buffer")) {
637 lwan->config.use_dynamic_buffer =
638 parse_bool(line->value, default_config.use_dynamic_buffer);
639 } else if (streq(line->key, "expires")) {
640 lwan->config.expires =
641 parse_time_period(line->value, default_config.expires);
642 } else if (streq(line->key, "error_template")) {
643 free(lwan->config.error_template);
644 lwan->config.error_template = strdup(line->value);
645 } else if (streq(line->key, "threads")) {
646 long n_threads =
647 parse_long(line->value, default_config.n_threads);
648 if (n_threads < 0)
649 config_error(conf, "Invalid number of threads: %ld",
650 n_threads);
651 lwan->config.n_threads = (unsigned int)n_threads;
652 } else if (streq(line->key, "request_buffer_size")) {
653 long request_buffer_size = parse_long(
654 line->value, (long)default_config.request_buffer_size);
655
656 if (request_buffer_size < 0) {
657 config_error(conf, "Negative request buffer size requested");
658 } else if (request_buffer_size > 16 * (1 << 20)) {
659 config_error(conf,
660 "Request buffer can't be over 16MiB");
661 } else if (request_buffer_size < DEFAULT_BUFFER_SIZE4096) {
662 lwan_status_warning("Request buffer size of %ld is smaller than the "lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 666, __FUNCTION__, "Request buffer size of %ld is smaller than the "
"recommended minimum of %d bytes. This might not " "be sufficient!"
, request_buffer_size, 4096)
663 "recommended minimum of %d bytes. This might not "lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 666, __FUNCTION__, "Request buffer size of %ld is smaller than the "
"recommended minimum of %d bytes. This might not " "be sufficient!"
, request_buffer_size, 4096)
664 "be sufficient!",lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 666, __FUNCTION__, "Request buffer size of %ld is smaller than the "
"recommended minimum of %d bytes. This might not " "be sufficient!"
, request_buffer_size, 4096)
665 request_buffer_size,lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 666, __FUNCTION__, "Request buffer size of %ld is smaller than the "
"recommended minimum of %d bytes. This might not " "be sufficient!"
, request_buffer_size, 4096)
666 DEFAULT_BUFFER_SIZE)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 666, __FUNCTION__, "Request buffer size of %ld is smaller than the "
"recommended minimum of %d bytes. This might not " "be sufficient!"
, request_buffer_size, 4096)
;
667 }
668
669 lwan->config.request_buffer_size = (size_t)request_buffer_size;
670 } else if (streq(line->key, "max_post_data_size")) {
671 long max_post_data_size = parse_long(
672 line->value, (long)default_config.max_post_data_size);
673
674 if (max_post_data_size < 0) {
675 config_error(conf, "Negative maximum post data size");
676 } else if (max_post_data_size > 128 * (1 << 20)) {
677 config_error(conf,
678 "Maximum post data can't be over 128MiB");
679 }
680
681 lwan->config.max_post_data_size = (size_t)max_post_data_size;
682 } else if (streq(line->key, "max_put_data_size")) {
683 long max_put_data_size = parse_long(
684 line->value, (long)default_config.max_put_data_size);
685
686 if (max_put_data_size < 0) {
687 config_error(conf, "Negative maximum put data size");
688 } else if (max_put_data_size > 128 * (1 << 20)) {
689 config_error(conf,
690 "Maximum put data can't be over 128MiB");
691 }
692 lwan->config.max_put_data_size = (size_t)max_put_data_size;
693 } else if (streq(line->key, "allow_temp_files")) {
694 bool_Bool has_post, has_put;
695
696 if (strstr(line->value, "all")) {
697 has_post = has_put = true1;
698 } else {
699 has_post = !!strstr(line->value, "post");
700 has_put = !!strstr(line->value, "put");
701 }
702
703 lwan->config.allow_post_temp_file = has_post;
704 lwan->config.allow_put_temp_file = has_put;
705 } else {
706 config_error(conf, "Unknown config key: %s", line->key);
707 }
708 break;
709 case CONFIG_LINE_TYPE_SECTION:
710 if (streq(line->key, "site")) {
11
Taking true branch
711 if (!has_site
11.1
'has_site' is false
) {
12
Taking true branch
712 parse_site(conf, line, lwan);
13
Calling 'parse_site'
713 has_site = true1;
714 } else {
715 config_error(conf, "Only one site may be configured");
716 }
717 } else if (streq(line->key, "straitjacket")) {
718 lwan_straitjacket_enforce_from_config(conf);
719 } else if (streq(line->key, "headers")) {
720 parse_global_headers(conf, lwan);
721 } else if (streq(line->key, "listener")) {
722 if (has_listener) {
723 config_error(conf, "Listener already set up");
724 } else {
725 parse_listener(conf, line, lwan);
726 has_listener = true1;
727 }
728 } else if (streq(line->key, "tls_listener")) {
729 if (has_tls_listener) {
730 config_error(conf, "TLS Listener already set up");
731 } else {
732 parse_tls_listener(conf, line, lwan);
733 has_tls_listener = true1;
734 }
735 } else {
736 config_error(conf, "Unknown section type: %s", line->key);
737 }
738 break;
739 case CONFIG_LINE_TYPE_SECTION_END:
740 config_error(conf, "Unexpected section end");
741 }
742 }
743
744 if (config_last_error(conf)) {
745 lwan_status_critical("Error on config file \"%s\", line %d: %s", path,lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 746, __FUNCTION__, "Error on config file \"%s\", line %d: %s"
, path, config_cur_line(conf), config_last_error(conf))
746 config_cur_line(conf), config_last_error(conf))lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 746, __FUNCTION__, "Error on config file \"%s\", line %d: %s"
, path, config_cur_line(conf), config_last_error(conf))
;
747 lwan_trie_destroy(&lwan->url_map_trie);
748 }
749
750 config_close(conf);
751
752 return true1;
753}
754
755static void try_setup_from_config(struct lwan *l,
756 const struct lwan_config *config)
757{
758 if (!setup_from_config(l, config->config_file_path)) {
3
Calling 'setup_from_config'
759 if (config->config_file_path) {
760 lwan_status_critical("Could not read config file: %s",lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 761, __FUNCTION__, "Could not read config file: %s", config
->config_file_path)
761 config->config_file_path)lwan_status_critical_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 761, __FUNCTION__, "Could not read config file: %s", config
->config_file_path)
;
762 }
763 }
764
765 lwan_status_init(l); /* `quiet` key might have changed value. */
766
767 l->config.request_flags =
768 (l->config.proxy_protocol ? REQUEST_ALLOW_PROXY_REQS : 0) |
769 (l->config.allow_cors ? REQUEST_ALLOW_CORS : 0) |
770 (l->config.ssl.send_hsts_header ? REQUEST_WANTS_HSTS_HEADER : 0);
771}
772
773static rlim_t setup_open_file_count_limits(void)
774{
775 struct rlimit r;
776
777 if (getrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &r) < 0) {
778 lwan_status_perror("Could not obtain maximum number of file "lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 780, __FUNCTION__, "Could not obtain maximum number of file "
"descriptors. Assuming %d", 256)
779 "descriptors. Assuming %d",lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 780, __FUNCTION__, "Could not obtain maximum number of file "
"descriptors. Assuming %d", 256)
780 OPEN_MAX)lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 780, __FUNCTION__, "Could not obtain maximum number of file "
"descriptors. Assuming %d", 256)
;
781 return OPEN_MAX256;
782 }
783
784 if (r.rlim_max != r.rlim_cur) {
785 const rlim_t current = r.rlim_cur;
786
787 if (r.rlim_max == RLIM_INFINITY0xffffffffffffffffuLL && r.rlim_cur < OPEN_MAX256) {
788 r.rlim_cur = OPEN_MAX256;
789 } else if (r.rlim_cur < r.rlim_max) {
790 r.rlim_cur = r.rlim_max;
791 } else {
792 /* Shouldn't happen, so just return the current value. */
793 goto out;
794 }
795
796 if (setrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &r) < 0) {
797 lwan_status_perror("Could not raise maximum number of file "lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 799, __FUNCTION__, "Could not raise maximum number of file "
"descriptors to %" "l" "u" ". Leaving at " "%" "l" "u", r.rlim_max
, current)
798 "descriptors to %" PRIu64 ". Leaving at "lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 799, __FUNCTION__, "Could not raise maximum number of file "
"descriptors to %" "l" "u" ". Leaving at " "%" "l" "u", r.rlim_max
, current)
799 "%" PRIu64, r.rlim_max, current)lwan_status_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 799, __FUNCTION__, "Could not raise maximum number of file "
"descriptors to %" "l" "u" ". Leaving at " "%" "l" "u", r.rlim_max
, current)
;
800 r.rlim_cur = current;
801 }
802 }
803
804out:
805 return r.rlim_cur;
806}
807
808static void allocate_connections(struct lwan *l, size_t max_open_files)
809{
810 const size_t sz = max_open_files * sizeof(struct lwan_connection);
811
812 l->conns = lwan_aligned_alloc(sz, 64);
813 if (UNLIKELY(!l->conns)__builtin_expect(((!l->conns)), (0)))
814 lwan_status_critical_perror("lwan_alloc_aligned")lwan_status_critical_perror_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 814, __FUNCTION__, "lwan_alloc_aligned")
;
815
816 memset(l->conns, 0, sz);
817}
818
819static void get_number_of_cpus(struct lwan *l)
820{
821 long n_online_cpus = sysconf(_SC_NPROCESSORS_ONLN_SC_NPROCESSORS_ONLN);
822 long n_available_cpus = sysconf(_SC_NPROCESSORS_CONF_SC_NPROCESSORS_CONF);
823
824 if (n_online_cpus < 0) {
825 lwan_status_warning(lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 826, __FUNCTION__, "Could not get number of online CPUs, assuming 1 CPU"
)
826 "Could not get number of online CPUs, assuming 1 CPU")lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 826, __FUNCTION__, "Could not get number of online CPUs, assuming 1 CPU"
)
;
827 n_online_cpus = 1;
828 }
829
830 if (n_available_cpus < 0) {
831 lwan_status_warning(lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 833, __FUNCTION__, "Could not get number of available CPUs, assuming %ld CPUs"
, n_online_cpus)
832 "Could not get number of available CPUs, assuming %ld CPUs",lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 833, __FUNCTION__, "Could not get number of available CPUs, assuming %ld CPUs"
, n_online_cpus)
833 n_online_cpus)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 833, __FUNCTION__, "Could not get number of available CPUs, assuming %ld CPUs"
, n_online_cpus)
;
834 n_available_cpus = n_online_cpus;
835 }
836
837 l->online_cpus = (unsigned int)n_online_cpus;
838 l->available_cpus = (unsigned int)n_available_cpus;
839}
840
841void lwan_init(struct lwan *l) { lwan_init_with_config(l, &default_config); }
1
Calling 'lwan_init_with_config'
842
843const struct lwan_config *lwan_get_default_config(void)
844{
845 return &default_config;
846}
847
848static char *dup_or_null(const char *s)
849{
850 return s ? strdup(s) : NULL((void*)0);
851}
852
853void lwan_init_with_config(struct lwan *l, const struct lwan_config *config)
854{
855 /* Load defaults */
856 memset(l, 0, sizeof(*l));
857 memcpy(&l->config, config, sizeof(*config));
858 l->config.listener = dup_or_null(l->config.listener);
859 l->config.config_file_path = dup_or_null(l->config.config_file_path);
860 l->config.ssl.key = dup_or_null(l->config.ssl.key);
861 l->config.ssl.cert = dup_or_null(l->config.ssl.cert);
862
863 /* Initialize status first, as it is used by other things during
864 * their initialization. */
865 lwan_status_init(l);
866
867 /* These will only print debugging messages. Debug messages are always
868 * printed if we're on a debug build, so the quiet setting will be
869 * respected. */
870 lwan_job_thread_init();
871 lwan_tables_init();
872
873 /* Get the number of CPUs here because straightjacket might be active
874 * and this will block access to /proc and /sys, which will cause
875 * get_number_of_cpus() to get incorrect fallback values. */
876 get_number_of_cpus(l);
877
878 try_setup_from_config(l, config);
2
Calling 'try_setup_from_config'
879
880 if (!l->headers.len)
881 build_response_headers(l, config->global_headers);
882
883 lwan_response_init(l);
884
885 /* Continue initialization as normal. */
886 lwan_status_debug("Initializing lwan web server")lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 886, __FUNCTION__, "Initializing lwan web server")
;
887
888 if (!l->config.n_threads) {
889 l->thread.count = l->online_cpus;
890 if (l->thread.count == 1)
891 l->thread.count = 2;
892 } else if (l->config.n_threads > 3 * l->online_cpus) {
893 l->thread.count = l->online_cpus * 3;
894
895 lwan_status_warning("%d threads requested, but only %d online CPUs "lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 898, __FUNCTION__, "%d threads requested, but only %d online CPUs "
"(out of %d configured CPUs); capping to %d threads", l->
config.n_threads, l->online_cpus, l->available_cpus, 3 *
l->online_cpus)
896 "(out of %d configured CPUs); capping to %d threads",lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 898, __FUNCTION__, "%d threads requested, but only %d online CPUs "
"(out of %d configured CPUs); capping to %d threads", l->
config.n_threads, l->online_cpus, l->available_cpus, 3 *
l->online_cpus)
897 l->config.n_threads, l->online_cpus, l->available_cpus,lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 898, __FUNCTION__, "%d threads requested, but only %d online CPUs "
"(out of %d configured CPUs); capping to %d threads", l->
config.n_threads, l->online_cpus, l->available_cpus, 3 *
l->online_cpus)
898 3 * l->online_cpus)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 898, __FUNCTION__, "%d threads requested, but only %d online CPUs "
"(out of %d configured CPUs); capping to %d threads", l->
config.n_threads, l->online_cpus, l->available_cpus, 3 *
l->online_cpus)
;
899 } else if (l->config.n_threads > 255) {
900 l->thread.count = 256;
901
902 lwan_status_warning("%d threads requested, but max 256 supported",lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 903, __FUNCTION__, "%d threads requested, but max 256 supported"
, l->config.n_threads)
903 l->config.n_threads)lwan_status_warning_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 903, __FUNCTION__, "%d threads requested, but max 256 supported"
, l->config.n_threads)
;
904 } else {
905 l->thread.count = l->config.n_threads;
906 }
907
908 rlim_t max_open_files = setup_open_file_count_limits();
909 allocate_connections(l, (size_t)max_open_files);
910
911 l->thread.max_fd = (unsigned)max_open_files / (unsigned)l->thread.count;
912 lwan_status_info("Using %d threads, maximum %d sockets per thread",lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 913, __FUNCTION__, "Using %d threads, maximum %d sockets per thread"
, l->thread.count, l->thread.max_fd)
913 l->thread.count, l->thread.max_fd)lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 913, __FUNCTION__, "Using %d threads, maximum %d sockets per thread"
, l->thread.count, l->thread.max_fd)
;
914
915 signal(SIGPIPE13, SIG_IGN((__sighandler_t) 1));
916
917 lwan_readahead_init();
918 lwan_thread_init(l);
919 lwan_http_authorize_init();
920}
921
922void lwan_shutdown(struct lwan *l)
923{
924 lwan_status_info("Shutting down")lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 924, __FUNCTION__, "Shutting down")
;
925
926 free(l->config.listener);
927 free(l->config.error_template);
928 free(l->config.config_file_path);
929
930 lwan_always_bzero(l->config.ssl.cert, strlen(l->config.ssl.cert));
931 free(l->config.ssl.cert);
932 lwan_always_bzero(l->config.ssl.key, strlen(l->config.ssl.key));
933 free(l->config.ssl.key);
934
935 lwan_job_thread_shutdown();
936 lwan_thread_shutdown(l);
937
938 lwan_status_debug("Shutting down URL handlers")lwan_status_debug_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 938, __FUNCTION__, "Shutting down URL handlers")
;
939 lwan_trie_destroy(&l->url_map_trie);
940
941 free(l->headers.value);
942 free(l->conns);
943
944 lwan_response_shutdown(l);
945 lwan_tables_shutdown();
946 lwan_status_shutdown(l);
947 lwan_http_authorize_shutdown();
948 lwan_readahead_shutdown();
949}
950
951void lwan_main_loop(struct lwan *l)
952{
953 lwan_status_info("Ready to serve")lwan_status_info_debug("/home/buildbot/lwan-worker/clang-analyze/build/src/lib/lwan.c"
, 953, __FUNCTION__, "Ready to serve")
;
954
955 lwan_job_thread_main_loop();
956}
957
958#ifdef CLOCK_MONOTONIC_COARSE6
959__attribute__((constructor)) static void detect_fastest_monotonic_clock(void)
960{
961 struct timespec ts;
962
963 if (!clock_gettime(CLOCK_MONOTONIC_COARSE6, &ts))
964 monotonic_clock_id = CLOCK_MONOTONIC_COARSE6;
965}
966#endif
967
968void lwan_set_thread_name(const char *name)
969{
970 char thread_name[16];
971 char process_name[PATH_MAX4096];
972 char *tmp;
973 int ret;
974
975 if (proc_pidpath(getpid(), process_name, sizeof(process_name)) < 0)
976 return;
977
978 tmp = strrchr(process_name, '/');
979 if (!tmp)
980 return;
981
982 ret = snprintf(thread_name, sizeof(thread_name), "%s %s", tmp + 1, name);
983 if (ret < 0)
984 return;
985
986 pthread_set_name_np(pthread_self(), thread_name);
987}