~ubuntu-branches/ubuntu/lucid/libevent/lucid

« back to all changes in this revision

Viewing changes to evport.c

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2009-05-15 20:11:06 UTC
  • mfrom: (1.3.1 upstream) (5.2.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090515201106-auauq7m2l4sej5n9
Tags: 1.4.11-stable-1
* New upstream release 
  - Fix a bug when removing a timeout from the heap
  - Remove the limit on size of HTTP headers by removing static buffers
  - Fix a nasty dangling pointer bug in epoll.c that could occur after
    epoll_recalc() 

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 * 3. The name of the author may not be used to endorse or promote products
13
13
 *    derived from this software without specific prior written permission.
14
14
 *
15
 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
 
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
 
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
 
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
 
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20
 
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
 
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22
 
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
15
 * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
 
16
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
18
 * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
 
19
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
20
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
21
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
22
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
24
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25
25
 */
26
26
 
27
27
/*
28
 
 * Copyright (c) 2006 Sun Microsystems. All rights reserved.
 
28
 * Copyright (c) 2007 Sun Microsystems. All rights reserved.
29
29
 * Use is subject to license terms.
30
30
 */
31
31
 
47
47
 * necessary when large fd's come in. reassociate() takes care of maintaining
48
48
 * the proper file-descriptor/event-port associations.
49
49
 *
50
 
 * As in the select(2) implementation, signals are handled by evsignal, and
51
 
 * evport_recalc does almost nothing.
 
50
 * As in the select(2) implementation, signals are handled by evsignal.
52
51
 */
53
52
 
54
53
#ifdef HAVE_CONFIG_H
55
54
#include "config.h"
56
55
#endif
57
56
 
58
 
#ifdef HAVE_SYS_TIME_H
59
57
#include <sys/time.h>
60
 
#else
61
 
#include <sys/_time.h>
62
 
#endif
63
58
#include <assert.h>
64
59
#include <sys/queue.h>
65
 
#include <sys/tree.h>
66
60
#include <errno.h>
67
61
#include <poll.h>
68
62
#include <port.h>
118
112
        int             ed_nevents;     /* number of allocated fdi's     */
119
113
        struct fd_info *ed_fds;         /* allocated fdi table           */
120
114
        /* fdi's that we need to reassoc */
121
 
        struct fd_info *ed_pending[EVENTS_PER_GETN];
 
115
        int ed_pending[EVENTS_PER_GETN]; /* fd's with pending events */
122
116
};
123
117
 
124
118
static void*    evport_init     (struct event_base *);
125
119
static int      evport_add      (void *, struct event *);
126
120
static int      evport_del      (void *, struct event *);
127
 
static int      evport_recalc   (struct event_base *, void *, int);
128
121
static int      evport_dispatch (struct event_base *, void *, struct timeval *);
129
122
static void     evport_dealloc  (struct event_base *, void *);
130
123
 
131
124
const struct eventop evportops = {
132
 
        "event ports",
 
125
        "evport",
133
126
        evport_init,
134
127
        evport_add,
135
128
        evport_del,
136
 
        evport_recalc,
137
129
        evport_dispatch,
138
 
        evport_dealloc
 
130
        evport_dealloc,
 
131
        1 /* need reinit */
139
132
};
140
133
 
141
134
/*
146
139
evport_init(struct event_base *base)
147
140
{
148
141
        struct evport_data *evpd;
 
142
        int i;
149
143
        /*
150
144
         * Disable event ports when this environment variable is set 
151
145
         */
170
164
                return (NULL);
171
165
        }
172
166
        evpd->ed_nevents = DEFAULT_NFDS;
173
 
        memset(&evpd->ed_pending, 0, EVENTS_PER_GETN * sizeof(struct fd_info*));
 
167
        for (i = 0; i < EVENTS_PER_GETN; i++)
 
168
                evpd->ed_pending[i] = -1;
174
169
 
175
170
        evsignal_init(base);
176
171
 
240
235
grow(struct evport_data *epdp, int factor)
241
236
{
242
237
        struct fd_info *tmp;
243
 
        struct fd_info *old = epdp->ed_fds;
244
238
        int oldsize = epdp->ed_nevents;
245
239
        int newsize = factor * oldsize;
246
 
        int ii;
247
240
        assert(factor > 1);
248
241
 
249
242
        check_evportop(epdp);
254
247
        epdp->ed_fds = tmp;
255
248
        memset((char*) (epdp->ed_fds + oldsize), 0, 
256
249
            (newsize - oldsize)*sizeof(struct fd_info));
257
 
 
258
 
        /* The ev_pending array contains pointers into the released array. */
259
 
        for (ii = 0; ii < EVENTS_PER_GETN; ++ii) {
260
 
                if (epdp->ed_pending[ii] != 0) {
261
 
                        int offset = epdp->ed_pending[ii] - old;
262
 
                        epdp->ed_pending[ii] = epdp->ed_fds + offset;
263
 
                }
264
 
        }
265
 
        
266
250
        epdp->ed_nevents = newsize;
267
251
 
268
252
        check_evportop(epdp);
281
265
        int sysevents = FDI_TO_SYSEVENTS(fdip);
282
266
 
283
267
        if (sysevents != 0) {
284
 
                if ((-1 == port_associate(epdp->ed_port, PORT_SOURCE_FD,
285
 
                    fd, sysevents, NULL))) {
286
 
                        perror("port_associate");
287
 
                        return (-1);
288
 
                }
289
 
        } else {
290
 
                if (-1 == port_dissociate(epdp->ed_port, PORT_SOURCE_FD, fd)) {
291
 
                        perror("port_dissociate");
 
268
                if (port_associate(epdp->ed_port, PORT_SOURCE_FD,
 
269
                                   fd, sysevents, NULL) == -1) {
 
270
                        event_warn("port_associate");
292
271
                        return (-1);
293
272
                }
294
273
        }
337
316
         * loop below.
338
317
         */
339
318
        for (i = 0; i < EVENTS_PER_GETN; ++i) {
340
 
                struct fd_info *fdi = epdp->ed_pending[i];
 
319
                struct fd_info *fdi = NULL;
 
320
                if (epdp->ed_pending[i] != -1) {
 
321
                        fdi = &(epdp->ed_fds[epdp->ed_pending[i]]);
 
322
                }
341
323
 
342
324
                if (fdi != NULL && FDI_HAS_EVENTS(fdi)) {
343
325
                        int fd = FDI_HAS_READ(fdi) ? fdi->fdi_revt->ev_fd : 
344
326
                            fdi->fdi_wevt->ev_fd;
345
327
                        reassociate(epdp, fdi, fd);
346
 
                        epdp->ed_pending[i] = NULL;
 
328
                        epdp->ed_pending[i] = -1;
347
329
                }
348
330
        }
349
331
 
350
332
        if ((res = port_getn(epdp->ed_port, pevtlist, EVENTS_PER_GETN, 
351
333
                    (unsigned int *) &nevents, ts_p)) == -1) {
352
 
                if (errno == EINTR) {
 
334
                if (errno == EINTR || errno == EAGAIN) {
353
335
                        evsignal_process(base);
354
336
                        return (0);
355
337
                } else if (errno == ETIME) {
356
338
                        if (nevents == 0)
357
339
                                return (0);
358
340
                } else {
359
 
                        perror("port_getn");
 
341
                        event_warn("port_getn");
360
342
                        return (-1);
361
343
                }
362
344
        } else if (base->sig.evsignal_caught) {
373
355
 
374
356
                check_evportop(epdp);
375
357
                check_event(pevt);
 
358
                epdp->ed_pending[i] = fd;
376
359
 
377
360
                /*
378
361
                 * Figure out what kind of event it was 
388
371
                fdi = &(epdp->ed_fds[fd]);
389
372
 
390
373
                /*
391
 
                 * We now check for each of the possible events (READ or WRITE).
392
 
                 * If the event is not persistent, then we delete it. Then, we
393
 
                 * activate the event (which will cause its callback to be
394
 
                 * executed).
 
374
                 * We now check for each of the possible events (READ
 
375
                 * or WRITE).  Then, we activate the event (which will
 
376
                 * cause its callback to be executed).
395
377
                 */
396
378
 
397
379
                if ((res & EV_READ) && ((ev = fdi->fdi_revt) != NULL)) {
398
 
                        if (!(ev->ev_events & EV_PERSIST))
399
 
                                event_del(ev);
400
380
                        event_active(ev, res, 1);
401
381
                }
402
382
 
403
383
                if ((res & EV_WRITE) && ((ev = fdi->fdi_wevt) != NULL)) {
404
 
                        if (!(ev->ev_events & EV_PERSIST))
405
 
                                event_del(ev);
406
384
                        event_active(ev, res, 1);
407
385
                }
408
 
 
409
 
                /*
410
 
                 * If there are still events (they haven't been deleted), then
411
 
                 * we must reassociate the port, since the event port interface
412
 
                 * dissociates them automatically. 
413
 
                 *
414
 
                 * But we can't do it right away, because the event hasn't
415
 
                 * handled this event yet, so of course there's still data
416
 
                 * waiting!
417
 
                 */
418
 
                if(FDI_HAS_EVENTS(fdi)) {
419
 
                        epdp->ed_pending[i] = fdi;
420
 
                }
421
386
        } /* end of all events gotten */
422
387
 
423
388
        check_evportop(epdp);
427
392
 
428
393
 
429
394
/*
430
 
 * Copied from the version in select.c
431
 
 */
432
 
 
433
 
static int
434
 
evport_recalc(struct event_base *base, void *arg, int max)
435
 
{
436
 
        struct evport_data *evpd = arg;
437
 
        check_evportop(evpd);
438
 
        return (0);
439
 
}
440
 
 
441
 
 
442
 
/*
443
395
 * Adds the given event (so that you will be notified when it happens via
444
396
 * the callback function).
445
397
 */
491
443
{
492
444
        struct evport_data *evpd = arg;
493
445
        struct fd_info *fdi;
 
446
        int i;
 
447
        int associated = 1;
494
448
 
495
449
        check_evportop(evpd);
496
450
 
505
459
                return (-1);
506
460
        }
507
461
 
 
462
        for (i = 0; i < EVENTS_PER_GETN; ++i) {
 
463
                if (evpd->ed_pending[i] == ev->ev_fd) {
 
464
                        associated = 0;
 
465
                        break;
 
466
                }
 
467
        }
508
468
 
509
469
        fdi = &evpd->ed_fds[ev->ev_fd];
510
470
        if (ev->ev_events & EV_READ)
512
472
        if (ev->ev_events & EV_WRITE)
513
473
                fdi->fdi_wevt = NULL;
514
474
 
515
 
        return reassociate(evpd, fdi, ev->ev_fd);
 
475
        if (associated) {
 
476
                if (!FDI_HAS_EVENTS(fdi) &&
 
477
                    port_dissociate(evpd->ed_port, PORT_SOURCE_FD,
 
478
                    ev->ev_fd) == -1) {  
 
479
                        /*
 
480
                         * Ignre EBADFD error the fd could have been closed
 
481
                         * before event_del() was called.
 
482
                         */
 
483
                        if (errno != EBADFD) {
 
484
                                event_warn("port_dissociate");
 
485
                                return (-1);
 
486
                        }
 
487
                } else {
 
488
                        if (FDI_HAS_EVENTS(fdi)) {
 
489
                                return (reassociate(evpd, fdi, ev->ev_fd));
 
490
                        }
 
491
                }
 
492
        } else {
 
493
                if (fdi->fdi_revt == NULL && fdi->fdi_wevt == NULL) {
 
494
                        evpd->ed_pending[i] = -1;
 
495
                }
 
496
        }
 
497
        return 0;
516
498
}
517
499
 
518
500