Bug Summary

File:libglusterfs/src/event-poll.c
Location:line 394, column 36
Description:Dereference of null pointer

Annotated Source Code

1/*
2 Copyright (c) 2012 Red Hat, Inc. <http://www.redhat.com>
3 This file is part of GlusterFS.
4
5 This file is licensed to you under your choice of the GNU Lesser
6 General Public License, version 3 or any later version (LGPLv3 or
7 later), or the GNU General Public License, version 2 (GPLv2), in all
8 cases as published by the Free Software Foundation.
9*/
10
11#include <sys/poll.h>
12#include <pthread.h>
13#include <unistd.h>
14#include <fcntl.h>
15#include <stdlib.h>
16#include <errno(*__errno_location ()).h>
17#include <string.h>
18
19#include "logging.h"
20#include "event.h"
21#include "mem-pool.h"
22#include "common-utils.h"
23
24#ifndef _CONFIG_H
25#define _CONFIG_H
26#include "config.h"
27#endif
28
29static int
30event_register_poll (struct event_pool *event_pool, int fd,
31 event_handler_t handler,
32 void *data, int poll_in, int poll_out);
33
34
35static int
36__flush_fd (int fd, int idx, void *data,
37 int poll_in, int poll_out, int poll_err)
38{
39 char buf[64];
40 int ret = -1;
41
42 if (!poll_in)
43 return ret;
44
45 do {
46 ret = read (fd, buf, 64);
47 if (ret == -1 && errno(*__errno_location ()) != EAGAIN11) {
48 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("read on %d returned error (%s)", fd
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 50, GF_LOG_ERROR, "read on %d returned error (%s)"
, fd, strerror ((*__errno_location ()))); } while (0)
49 "read on %d returned error (%s)",do { do { if (0) printf ("read on %d returned error (%s)", fd
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 50, GF_LOG_ERROR, "read on %d returned error (%s)"
, fd, strerror ((*__errno_location ()))); } while (0)
50 fd, strerror (errno))do { do { if (0) printf ("read on %d returned error (%s)", fd
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 50, GF_LOG_ERROR, "read on %d returned error (%s)"
, fd, strerror ((*__errno_location ()))); } while (0)
;
51 }
52 } while (ret == 64);
53
54 return ret;
55}
56
57
58static int
59__event_getindex (struct event_pool *event_pool, int fd, int idx)
60{
61 int ret = -1;
62 int i = 0;
63
64 GF_VALIDATE_OR_GOTO ("event", event_pool, out)do { if (!event_pool) { (*__errno_location ()) = 22; do { do {
if (0) printf ("invalid argument: " "event_pool"); } while (
0); _gf_log_callingfn ("event", "event-poll.c", __FUNCTION__,
64, GF_LOG_ERROR, "invalid argument: " "event_pool"); } while
(0); goto out; } } while (0)
;
65
66 if (idx > -1 && idx < event_pool->used) {
67 if (event_pool->reg[idx].fd == fd)
68 ret = idx;
69 }
70
71 for (i=0; ret == -1 && i<event_pool->used; i++) {
72 if (event_pool->reg[i].fd == fd) {
73 ret = i;
74 break;
75 }
76 }
77
78out:
79 return ret;
80}
81
82
83static struct event_pool *
84event_pool_new_poll (int count)
85{
86 struct event_pool *event_pool = NULL((void*)0);
87 int ret = -1;
88
89 event_pool = GF_CALLOC (1, sizeof (*event_pool),__gf_calloc (1, sizeof (*event_pool), gf_common_mt_event_pool
)
90 gf_common_mt_event_pool)__gf_calloc (1, sizeof (*event_pool), gf_common_mt_event_pool
)
;
91
92 if (!event_pool)
93 return NULL((void*)0);
94
95 event_pool->count = count;
96 event_pool->reg = GF_CALLOC (event_pool->count,__gf_calloc (event_pool->count, sizeof (*event_pool->reg
), gf_common_mt_reg)
97 sizeof (*event_pool->reg),__gf_calloc (event_pool->count, sizeof (*event_pool->reg
), gf_common_mt_reg)
98 gf_common_mt_reg)__gf_calloc (event_pool->count, sizeof (*event_pool->reg
), gf_common_mt_reg)
;
99
100 if (!event_pool->reg) {
101 GF_FREE (event_pool)__gf_free (event_pool);
102 return NULL((void*)0);
103 }
104
105 pthread_mutex_init (&event_pool->mutex, NULL((void*)0));
106
107 ret = pipe (event_pool->breaker);
108
109 if (ret == -1) {
110 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("pipe creation failed (%s)", strerror
((*__errno_location ()))); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 111, GF_LOG_ERROR, "pipe creation failed (%s)"
, strerror ((*__errno_location ()))); } while (0)
111 "pipe creation failed (%s)", strerror (errno))do { do { if (0) printf ("pipe creation failed (%s)", strerror
((*__errno_location ()))); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 111, GF_LOG_ERROR, "pipe creation failed (%s)"
, strerror ((*__errno_location ()))); } while (0)
;
112 GF_FREE (event_pool->reg)__gf_free (event_pool->reg);
113 GF_FREE (event_pool)__gf_free (event_pool);
114 return NULL((void*)0);
115 }
116
117 ret = fcntl (event_pool->breaker[0], F_SETFL4, O_NONBLOCK04000);
118 if (ret == -1) {
119 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 121, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
120 "could not set pipe to non blocking mode (%s)",do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 121, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
121 strerror (errno))do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 121, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
;
122 close (event_pool->breaker[0]);
123 close (event_pool->breaker[1]);
124 event_pool->breaker[0] = event_pool->breaker[1] = -1;
125
126 GF_FREE (event_pool->reg)__gf_free (event_pool->reg);
127 GF_FREE (event_pool)__gf_free (event_pool);
128 return NULL((void*)0);
129 }
130
131 ret = fcntl (event_pool->breaker[1], F_SETFL4, O_NONBLOCK04000);
132 if (ret == -1) {
133 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 135, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
134 "could not set pipe to non blocking mode (%s)",do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 135, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
135 strerror (errno))do { do { if (0) printf ("could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0); _gf_log ("poll"
, "event-poll.c", __FUNCTION__, 135, GF_LOG_ERROR, "could not set pipe to non blocking mode (%s)"
, strerror ((*__errno_location ()))); } while (0)
;
136
137 close (event_pool->breaker[0]);
138 close (event_pool->breaker[1]);
139 event_pool->breaker[0] = event_pool->breaker[1] = -1;
140
141 GF_FREE (event_pool->reg)__gf_free (event_pool->reg);
142 GF_FREE (event_pool)__gf_free (event_pool);
143 return NULL((void*)0);
144 }
145
146 ret = event_register_poll (event_pool, event_pool->breaker[0],
147 __flush_fd, NULL((void*)0), 1, 0);
148 if (ret == -1) {
149 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("could not register pipe fd with poll event loop"
); } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__
, 150, GF_LOG_ERROR, "could not register pipe fd with poll event loop"
); } while (0)
150 "could not register pipe fd with poll event loop")do { do { if (0) printf ("could not register pipe fd with poll event loop"
); } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__
, 150, GF_LOG_ERROR, "could not register pipe fd with poll event loop"
); } while (0)
;
151 close (event_pool->breaker[0]);
152 close (event_pool->breaker[1]);
153 event_pool->breaker[0] = event_pool->breaker[1] = -1;
154
155 GF_FREE (event_pool->reg)__gf_free (event_pool->reg);
156 GF_FREE (event_pool)__gf_free (event_pool);
157 return NULL((void*)0);
158 }
159
160 return event_pool;
161}
162
163
164static int
165event_register_poll (struct event_pool *event_pool, int fd,
166 event_handler_t handler,
167 void *data, int poll_in, int poll_out)
168{
169 int idx = -1;
170
171 GF_VALIDATE_OR_GOTO ("event", event_pool, out)do { if (!event_pool) { (*__errno_location ()) = 22; do { do {
if (0) printf ("invalid argument: " "event_pool"); } while (
0); _gf_log_callingfn ("event", "event-poll.c", __FUNCTION__,
171, GF_LOG_ERROR, "invalid argument: " "event_pool"); } while
(0); goto out; } } while (0)
;
172
173 pthread_mutex_lock (&event_pool->mutex);
174 {
175 if (event_pool->count == event_pool->used)
176 {
177 event_pool->count += 256;
178
179 event_pool->reg = GF_REALLOC (event_pool->reg,__gf_realloc (event_pool->reg, event_pool->count * sizeof
(*event_pool->reg))
180 event_pool->count *__gf_realloc (event_pool->reg, event_pool->count * sizeof
(*event_pool->reg))
181 sizeof (*event_pool->reg))__gf_realloc (event_pool->reg, event_pool->count * sizeof
(*event_pool->reg))
;
182 if (!event_pool->reg)
183 goto unlock;
184 }
185
186 idx = event_pool->used++;
187
188 event_pool->reg[idx].fd = fd;
189 event_pool->reg[idx].events = POLLPRI0x002;
190 event_pool->reg[idx].handler = handler;
191 event_pool->reg[idx].data = data;
192
193 switch (poll_in) {
194 case 1:
195 event_pool->reg[idx].events |= POLLIN0x001;
196 break;
197 case 0:
198 event_pool->reg[idx].events &= ~POLLIN0x001;
199 break;
200 case -1:
201 /* do nothing */
202 break;
203 default:
204 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("invalid poll_in value %d", poll_in)
; } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__,
205, GF_LOG_ERROR, "invalid poll_in value %d", poll_in); } while
(0)
205 "invalid poll_in value %d", poll_in)do { do { if (0) printf ("invalid poll_in value %d", poll_in)
; } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__,
205, GF_LOG_ERROR, "invalid poll_in value %d", poll_in); } while
(0)
;
206 break;
207 }
208
209 switch (poll_out) {
210 case 1:
211 event_pool->reg[idx].events |= POLLOUT0x004;
212 break;
213 case 0:
214 event_pool->reg[idx].events &= ~POLLOUT0x004;
215 break;
216 case -1:
217 /* do nothing */
218 break;
219 default:
220 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("invalid poll_out value %d", poll_out
); } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__
, 221, GF_LOG_ERROR, "invalid poll_out value %d", poll_out); }
while (0)
221 "invalid poll_out value %d", poll_out)do { do { if (0) printf ("invalid poll_out value %d", poll_out
); } while (0); _gf_log ("poll", "event-poll.c", __FUNCTION__
, 221, GF_LOG_ERROR, "invalid poll_out value %d", poll_out); }
while (0)
;
222 break;
223 }
224
225 event_pool->changed = 1;
226
227 }
228unlock:
229 pthread_mutex_unlock (&event_pool->mutex);
230
231out:
232 return idx;
233}
234
235
236static int
237event_unregister_poll (struct event_pool *event_pool, int fd, int idx_hint)
238{
239 int idx = -1;
240
241 GF_VALIDATE_OR_GOTO ("event", event_pool, out)do { if (!event_pool) { (*__errno_location ()) = 22; do { do {
if (0) printf ("invalid argument: " "event_pool"); } while (
0); _gf_log_callingfn ("event", "event-poll.c", __FUNCTION__,
241, GF_LOG_ERROR, "invalid argument: " "event_pool"); } while
(0); goto out; } } while (0)
;
242
243 pthread_mutex_lock (&event_pool->mutex);
244 {
245 idx = __event_getindex (event_pool, fd, idx_hint);
246
247 if (idx == -1) {
248 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 250, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
249 "index not found for fd=%d (idx_hint=%d)",do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 250, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
250 fd, idx_hint)do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 250, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
;
251 errno(*__errno_location ()) = ENOENT2;
252 goto unlock;
253 }
254
255 event_pool->reg[idx] = event_pool->reg[--event_pool->used];
256 event_pool->changed = 1;
257 }
258unlock:
259 pthread_mutex_unlock (&event_pool->mutex);
260
261out:
262 return idx;
263}
264
265
266static int
267event_select_on_poll (struct event_pool *event_pool, int fd, int idx_hint,
268 int poll_in, int poll_out)
269{
270 int idx = -1;
271
272 GF_VALIDATE_OR_GOTO ("event", event_pool, out)do { if (!event_pool) { (*__errno_location ()) = 22; do { do {
if (0) printf ("invalid argument: " "event_pool"); } while (
0); _gf_log_callingfn ("event", "event-poll.c", __FUNCTION__,
272, GF_LOG_ERROR, "invalid argument: " "event_pool"); } while
(0); goto out; } } while (0)
;
273
274 pthread_mutex_lock (&event_pool->mutex);
275 {
276 idx = __event_getindex (event_pool, fd, idx_hint);
277
278 if (idx == -1) {
279 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 281, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
280 "index not found for fd=%d (idx_hint=%d)",do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 281, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
281 fd, idx_hint)do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 281, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, fd, idx_hint); } while (0)
;
282 errno(*__errno_location ()) = ENOENT2;
283 goto unlock;
284 }
285
286 switch (poll_in) {
287 case 1:
288 event_pool->reg[idx].events |= POLLIN0x001;
289 break;
290 case 0:
291 event_pool->reg[idx].events &= ~POLLIN0x001;
292 break;
293 case -1:
294 /* do nothing */
295 break;
296 default:
297 /* TODO: log error */
298 break;
299 }
300
301 switch (poll_out) {
302 case 1:
303 event_pool->reg[idx].events |= POLLOUT0x004;
304 break;
305 case 0:
306 event_pool->reg[idx].events &= ~POLLOUT0x004;
307 break;
308 case -1:
309 /* do nothing */
310 break;
311 default:
312 /* TODO: log error */
313 break;
314 }
315
316 if (poll_in + poll_out > -2)
317 event_pool->changed = 1;
318 }
319unlock:
320 pthread_mutex_unlock (&event_pool->mutex);
321
322out:
323 return idx;
324}
325
326
327static int
328event_dispatch_poll_handler (struct event_pool *event_pool,
329 struct pollfd *ufds, int i)
330{
331 event_handler_t handler = NULL((void*)0);
332 void *data = NULL((void*)0);
333 int idx = -1;
334 int ret = 0;
335
336 handler = NULL((void*)0);
337 data = NULL((void*)0);
338
339 pthread_mutex_lock (&event_pool->mutex);
340 {
341 idx = __event_getindex (event_pool, ufds[i].fd, i);
342
343 if (idx == -1) {
344 gf_log ("poll", GF_LOG_ERROR,do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 346, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0)
345 "index not found for fd=%d (idx_hint=%d)",do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 346, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0)
346 ufds[i].fd, i)do { do { if (0) printf ("index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0); _gf_log ("poll", "event-poll.c"
, __FUNCTION__, 346, GF_LOG_ERROR, "index not found for fd=%d (idx_hint=%d)"
, ufds[i].fd, i); } while (0)
;
347 goto unlock;
348 }
349
350 handler = event_pool->reg[idx].handler;
351 data = event_pool->reg[idx].data;
352 }
353unlock:
354 pthread_mutex_unlock (&event_pool->mutex);
355
356 if (handler)
357 ret = handler (ufds[i].fd, idx, data,
358 (ufds[i].revents & (POLLIN0x001|POLLPRI0x002)),
359 (ufds[i].revents & (POLLOUT0x004)),
360 (ufds[i].revents & (POLLERR0x008|POLLHUP0x010|POLLNVAL0x020)));
361
362 return ret;
363}
364
365
366static int
367event_dispatch_poll_resize (struct event_pool *event_pool,
368 struct pollfd *ufds, int size)
369{
370 int i = 0;
371
372 pthread_mutex_lock (&event_pool->mutex);
373 {
374 if (event_pool->changed == 0) {
5
Taking false branch
375 goto unlock;
376 }
377
378 if (event_pool->used > event_pool->evcache_size) {
6
Taking false branch
379 GF_FREE (event_pool->evcache)__gf_free (event_pool->evcache);
380
381 event_pool->evcache = ufds = NULL((void*)0);
382
383 event_pool->evcache_size = event_pool->used;
384
385 ufds = GF_CALLOC (sizeof (struct pollfd),__gf_calloc (sizeof (struct pollfd), event_pool->evcache_size
, gf_common_mt_pollfd)
386 event_pool->evcache_size,__gf_calloc (sizeof (struct pollfd), event_pool->evcache_size
, gf_common_mt_pollfd)
387 gf_common_mt_pollfd)__gf_calloc (sizeof (struct pollfd), event_pool->evcache_size
, gf_common_mt_pollfd)
;
388 if (!ufds)
389 goto unlock;
390 event_pool->evcache = ufds;
391 }
392
393 for (i = 0; i < event_pool->used; i++) {
7
Loop condition is true. Entering loop body
394 ufds[i].fd = event_pool->reg[i].fd;
8
Dereference of null pointer
395 ufds[i].events = event_pool->reg[i].events;
396 ufds[i].revents = 0;
397 }
398
399 size = i;
400 }
401unlock:
402 pthread_mutex_unlock (&event_pool->mutex);
403
404 return size;
405}
406
407
408static int
409event_dispatch_poll (struct event_pool *event_pool)
410{
411 struct pollfd *ufds = NULL((void*)0);
1
'ufds' initialized to a null pointer value
412 int size = 0;
413 int i = 0;
414 int ret = -1;
415
416 GF_VALIDATE_OR_GOTO ("event", event_pool, out)do { if (!event_pool) { (*__errno_location ()) = 22; do { do {
if (0) printf ("invalid argument: " "event_pool"); } while (
0); _gf_log_callingfn ("event", "event-poll.c", __FUNCTION__,
416, GF_LOG_ERROR, "invalid argument: " "event_pool"); } while
(0); goto out; } } while (0)
;
417
418 while (1) {
2
Loop condition is true. Entering loop body
419 size = event_dispatch_poll_resize (event_pool, ufds, size);
3
Passing null pointer value via 2nd parameter 'ufds'
4
Calling 'event_dispatch_poll_resize'
420 ufds = event_pool->evcache;
421
422 ret = poll (ufds, size, 1);
423
424 if (ret == 0)
425 /* timeout */
426 continue;
427
428 if (ret == -1 && errno(*__errno_location ()) == EINTR4)
429 /* sys call */
430 continue;
431
432 for (i = 0; i < size; i++) {
433 if (!ufds[i].revents)
434 continue;
435
436 event_dispatch_poll_handler (event_pool, ufds, i);
437 }
438 }
439
440out:
441 return -1;
442}
443
444
445struct event_ops event_ops_poll = {
446 .new = event_pool_new_poll,
447 .event_register = event_register_poll,
448 .event_select_on = event_select_on_poll,
449 .event_unregister = event_unregister_poll,
450 .event_dispatch = event_dispatch_poll
451};