Bug Summary

File:lwan-job.c
Location:line 128, column 1
Description:Potential leak of memory pointed to by 'job'

Annotated Source Code

1/*
2 * lwan - simple web server
3 * Copyright (c) 2012, 2013 Leandro A. F. Pereira <leandro@hardinfo.org>
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, USA.
18 */
19
20#define _GNU_SOURCE
21#include <assert.h>
22#include <errno(*__errno_location ()).h>
23#include <pthread.h>
24#include <sched.h>
25#include <stdbool.h>
26#include <stdlib.h>
27#include <unistd.h>
28
29#include "lwan.h"
30#include "lwan-status.h"
31#include "list.h"
32
33struct job_t {
34 struct list_node jobs;
35 bool_Bool (*cb)(void *data);
36 void *data;
37};
38
39static pthread_t self;
40static pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } };
41static bool_Bool running = false0;
42static struct list_head jobs;
43
44static void*
45job_thread(void *data __attribute__((unused)))
46{
47 struct timespec rgtp = { 1, 0 };
48
49 while (running) {
50 bool_Bool had_job = false0;
51
52 if (LIKELY(!pthread_mutex_lock(&queue_mutex))__builtin_expect((!!(!pthread_mutex_lock(&queue_mutex))),
(1))
) {
53 struct job_t *job;
54
55 list_for_each(&jobs, job, jobs)for (job = list_node_to_off_((&jobs)->n.next, ((__builtin_offsetof
(typeof(*job), jobs) + ((typeof(job->jobs) *)0 != (struct list_node
*)0)))); list_node_from_off_((void *)job, ((__builtin_offsetof
(typeof(*job), jobs) + ((typeof(job->jobs) *)0 != (struct list_node
*)0)))) != &(&jobs)->n; job = list_node_to_off_(list_node_from_off_
((void *)job, ((__builtin_offsetof(typeof(*job), jobs) + ((typeof
(job->jobs) *)0 != (struct list_node *)0))))->next, ((__builtin_offsetof
(typeof(*job), jobs) + ((typeof(job->jobs) *)0 != (struct list_node
*)0)))))
56 had_job |= job->cb(job->data);
57
58 pthread_mutex_unlock(&queue_mutex);
59 }
60
61 if (had_job)
62 rgtp.tv_sec = 1;
63 else if (rgtp.tv_sec <= 15)
64 rgtp.tv_sec++;
65
66 if (UNLIKELY(nanosleep(&rgtp, NULL) < 0)__builtin_expect(((nanosleep(&rgtp, ((void*)0)) < 0)),
(0))
) {
67 if (errno(*__errno_location ()) == EINTR4)
68 sleep(1);
69 }
70 }
71
72 return NULL((void*)0);
73}
74
75void lwan_job_thread_init(void)
76{
77 assert(!running)((!running) ? (void) (0) : __assert_fail ("!running", "/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 77, __PRETTY_FUNCTION__))
;
78
79 lwan_status_debug("Initializing low priority job thread")lwan_status_debug_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 79, __FUNCTION__, "Initializing low priority job thread")
;
80
81 list_head_init(&jobs);
82
83 running = true1;
84 if (pthread_create(&self, NULL((void*)0), job_thread, NULL((void*)0)) < 0)
85 lwan_status_critical_perror("pthread_create")lwan_status_critical_perror_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 85, __FUNCTION__, "pthread_create")
;
86
87#ifdef SCHED_IDLE5
88 struct sched_param sched_param = {
89 .sched_priority__sched_priority = 0
90 };
91 if (pthread_setschedparam(self, SCHED_IDLE5, &sched_param) < 0)
92 lwan_status_perror("pthread_setschedparam")lwan_status_perror_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 92, __FUNCTION__, "pthread_setschedparam")
;
93#endif /* SCHED_IDLE */
94}
95
96void lwan_job_thread_shutdown(void)
97{
98 lwan_status_debug("Shutting down job thread")lwan_status_debug_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 98, __FUNCTION__, "Shutting down job thread")
;
99
100 if (LIKELY(!pthread_mutex_lock(&queue_mutex))__builtin_expect((!!(!pthread_mutex_lock(&queue_mutex))),
(1))
) {
101 struct job_t *node, *next;
102 list_for_each_safe(&jobs, node, next, jobs)for (node = list_node_to_off_((&jobs)->n.next, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))), next = list_node_to_off_(list_node_from_off_
(node, ((__builtin_offsetof(typeof(*node), jobs) + ((typeof(node
->jobs) *)0 != (struct list_node *)0))))->next, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))); list_node_from_off_(node, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))) != &(&jobs)->n; node = next, next
= list_node_to_off_(list_node_from_off_(node, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0))))->next, ((__builtin_offsetof(typeof(*node
), jobs) + ((typeof(node->jobs) *)0 != (struct list_node *
)0)))))
{
103 list_del(&node->jobs);
104 free(node);
105 }
106 running = false0;
107 if (pthread_tryjoin_np(self, NULL((void*)0)) < 0)
108 lwan_status_critical_perror("pthread_join")lwan_status_critical_perror_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 108, __FUNCTION__, "pthread_join")
;
109 pthread_mutex_unlock(&queue_mutex);
110 }
111}
112
113void lwan_job_add(bool_Bool (*cb)(void *data), void *data)
114{
115 assert(cb)((cb) ? (void) (0) : __assert_fail ("cb", "/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 115, __PRETTY_FUNCTION__))
;
116
117 struct job_t *job = calloc(1, sizeof(*job));
1
Memory is allocated
118 if (!job)
2
Assuming 'job' is non-null
3
Taking false branch
119 lwan_status_critical_perror("calloc")lwan_status_critical_perror_debug("/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 119, __FUNCTION__, "calloc")
;
120
121 job->cb = cb;
122 job->data = data;
123
124 if (LIKELY(!pthread_mutex_lock(&queue_mutex))__builtin_expect((!!(!pthread_mutex_lock(&queue_mutex))),
(1))
) {
4
Taking false branch
125 list_add(&jobs, &job->jobs);
126 pthread_mutex_unlock(&queue_mutex);
127 }
128}
5
Potential leak of memory pointed to by 'job'
129
130void lwan_job_del(bool_Bool (*cb)(void *data), void *data)
131{
132 struct job_t *node, *next;
133
134 assert(cb)((cb) ? (void) (0) : __assert_fail ("cb", "/home/buildbot/lwan-slave/clang-analyze/build/common/lwan-job.c"
, 134, __PRETTY_FUNCTION__))
;
135
136 if (LIKELY(!pthread_mutex_lock(&queue_mutex))__builtin_expect((!!(!pthread_mutex_lock(&queue_mutex))),
(1))
) {
137 list_for_each_safe(&jobs, node, next, jobs)for (node = list_node_to_off_((&jobs)->n.next, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))), next = list_node_to_off_(list_node_from_off_
(node, ((__builtin_offsetof(typeof(*node), jobs) + ((typeof(node
->jobs) *)0 != (struct list_node *)0))))->next, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))); list_node_from_off_(node, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0)))) != &(&jobs)->n; node = next, next
= list_node_to_off_(list_node_from_off_(node, ((__builtin_offsetof
(typeof(*node), jobs) + ((typeof(node->jobs) *)0 != (struct
list_node *)0))))->next, ((__builtin_offsetof(typeof(*node
), jobs) + ((typeof(node->jobs) *)0 != (struct list_node *
)0)))))
{
138 if (cb == node->cb && data == node->data) {
139 list_del(&node->jobs);
140 free(node);
141 }
142 }
143 pthread_mutex_unlock(&queue_mutex);
144 }
145}