~ubuntu-branches/ubuntu/trusty/syslog-ng/trusty-proposed

« back to all changes in this revision

Viewing changes to lib/ivykis/lib/iv_method_kqueue.c

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS), Gergely Nagy
  • Date: 2011-10-11 14:30:48 UTC
  • mfrom: (1.3.7)
  • Revision ID: package-import@ubuntu.com-20111011143048-r1iljux9xbvj3lwh
Tags: 3.3.1.dfsg-1
* New upstream release with important fixes from upstream git tree with
  non-free manpages removed.
* Drop syslog-ng.conf(5) (closes: #496521).
* syslog-ng(8) is generated, and does not mention -Q anymore
  (closes: #616069).
* Supports CAP_SYSLOG on recent kernels (closes: #630172).
* Does not use g_timeout_add_seconds anymore (closes: #609154).

[ Gergely Nagy <algernon@madhouse-project.org> ]
* Update debian/copyright to DEP-5 format.
* Simplified the logrotate file by merging identical entries.
* Include local configuration files from /etc/syslog-ng/conf.d/ (Closes:
  #609050).
* Update syslog-ng.conf to be fully 3.3 compliant.
* Compress both source and binaries (except the syslog-ng meta
  package) with xz, instead of gzip.
* Use dpkg triggers to restart syslog-ng when appropriate.
* Include DFSG-free manual pages for all binaries.
* Build with Hardening enabled.
* Mention syslog(3) in /etc/default/syslog-ng, instead of
  <linux/kernel.h> (Closes: #608605)
* Support 'status' in the init script.
  Patch from Peter Eisentraut <petere@debian.org> (Closes: #644458)
* Build-Depend on libevtlog-dev (>= 0.2.12-5~) for correct shlibs.
* Use [linux-any] in Build-Depends instead of hardcoded links.
  (Closes: #634715)
* Use $SYSLOGNG_OPTS in the init script when reloading syslog-ng.
  (Closes: #589081)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ivykis, an event handling library
 
3
 * Copyright (C) 2002, 2003, 2009 Lennert Buytenhek
 
4
 * Dedicated to Marija Kulikova.
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU Lesser General Public License version
 
8
 * 2.1 as published by the Free Software Foundation.
 
9
 *
 
10
 * This library 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 Lesser General Public License version 2.1 for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License version 2.1 along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
 
18
 * Boston, MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
#include <stdio.h>
 
22
#include <stdlib.h>
 
23
#include <fcntl.h>
 
24
#include <string.h>
 
25
#include <syslog.h>
 
26
#include <sys/types.h>
 
27
#include <sys/event.h>
 
28
#include <sys/time.h>
 
29
#include "iv_thr.h"
 
30
#include "iv_private.h"
 
31
 
 
32
#define UPLOAD_QUEUE_SIZE       (1024)
 
33
 
 
34
TLS_BEGIN_BLOCK
 
35
{
 
36
        int             kqueue_fd;
 
37
        struct kevent   *upload_queue;
 
38
        int             upload_entries;
 
39
}
 
40
TLS_END_BLOCK;
 
41
 
 
42
#define kqueue_fd         __tls_deref(kqueue_fd)
 
43
#define upload_queue      __tls_deref(upload_queue)
 
44
#define upload_entries    __tls_deref(upload_entries)
 
45
 
 
46
 
 
47
static int iv_kqueue_init(int maxfd)
 
48
{
 
49
        int flags;
 
50
 
 
51
        kqueue_fd = kqueue();
 
52
        if (kqueue_fd < 0)
 
53
                return -1;
 
54
 
 
55
        flags = fcntl(kqueue_fd, F_GETFD);
 
56
        if (!(flags & FD_CLOEXEC)) {
 
57
                flags |= FD_CLOEXEC;
 
58
                fcntl(kqueue_fd, F_SETFD, flags);
 
59
        }
 
60
 
 
61
        upload_queue = malloc(UPLOAD_QUEUE_SIZE * sizeof(*upload_queue));
 
62
        if (upload_queue == NULL) {
 
63
                close(kqueue_fd);
 
64
                return -1;
 
65
        }
 
66
 
 
67
        fprintf(stderr, "warning: using kqueue(2), POLLERR delivery broken\n");
 
68
 
 
69
        upload_entries = 0;
 
70
 
 
71
        return 0;
 
72
}
 
73
 
 
74
static void iv_kqueue_poll(int numfds, struct list_head *active, int msec)
 
75
{
 
76
        struct timespec to;
 
77
        struct kevent batch[numfds ? : 1];
 
78
        int ret;
 
79
        int i;
 
80
 
 
81
        /*
 
82
         * Valgrind 3.5.0 as supplied with FreeBSD 8.1-RELEASE ports
 
83
         * doesn't understand that kevent(2) fills in kevent udata on
 
84
         * return, and labels our subsequent use of it as "Conditional
 
85
         * jump or move depends on uninitialised value(s)".  Zero the
 
86
         * udata fields here as an ugly workaround.
 
87
         */
 
88
        for (i = 0; i < (numfds ? : 1); i++)
 
89
                batch[i].udata = 0;
 
90
 
 
91
        to.tv_sec = msec / 1000;
 
92
        to.tv_nsec = 1000000 * (msec % 1000);
 
93
 
 
94
        ret = kevent(kqueue_fd, upload_queue, upload_entries,
 
95
                     batch, numfds ? : 1, &to);
 
96
        if (ret < 0) {
 
97
                if (errno == EINTR)
 
98
                        return;
 
99
 
 
100
                fprintf(stderr, "iv_kqueue_poll: got error %d[%s]",
 
101
                       errno, strerror(errno));
 
102
                abort();
 
103
        }
 
104
 
 
105
        upload_entries = 0;
 
106
 
 
107
        for (i = 0; i < ret; i++) {
 
108
                struct iv_fd_ *fd;
 
109
 
 
110
                fd = batch[i].udata;
 
111
                if (batch[i].filter == EVFILT_READ) {
 
112
                        iv_fd_make_ready(active, fd, MASKIN);
 
113
                } else if (batch[i].filter == EVFILT_WRITE) {
 
114
                        iv_fd_make_ready(active, fd, MASKOUT);
 
115
                } else {
 
116
                        fprintf(stderr, "iv_kqueue_poll: got message from "
 
117
                                         "filter %d", batch[i].filter);
 
118
                        abort();
 
119
                }
 
120
        }
 
121
}
 
122
 
 
123
static void flush_upload_queue(void)
 
124
{
 
125
        struct timespec to = { 0, 0 };
 
126
        int ret;
 
127
 
 
128
        do {
 
129
                ret = kevent(kqueue_fd, upload_queue,
 
130
                             upload_entries, NULL, 0, &to);
 
131
        } while (ret < 0 && errno == EINTR);
 
132
 
 
133
        if (ret < 0) {
 
134
                fprintf(stderr, "flush_upload_queue: got error %d[%s]",
 
135
                       errno, strerror(errno));
 
136
                abort();
 
137
        }
 
138
 
 
139
        upload_entries = 0;
 
140
}
 
141
 
 
142
static void iv_kqueue_unregister_fd(struct iv_fd_ *fd)
 
143
{
 
144
        flush_upload_queue();
 
145
}
 
146
 
 
147
static void queue(u_int ident, short filter, u_short flags,
 
148
                  u_int fflags, int data, void *udata)
 
149
{
 
150
        if (upload_entries == UPLOAD_QUEUE_SIZE)
 
151
                flush_upload_queue();
 
152
 
 
153
        EV_SET(&upload_queue[upload_entries], ident, filter, flags,
 
154
               fflags, data, udata);
 
155
        upload_entries++;
 
156
}
 
157
 
 
158
static void iv_kqueue_notify_fd(struct iv_fd_ *fd, int wanted)
 
159
{
 
160
        if ((fd->registered_bands & MASKIN) && !(wanted & MASKIN)) {
 
161
                queue(fd->fd, EVFILT_READ, EV_DELETE, 0, 0, (void *)fd);
 
162
                fd->registered_bands &= ~MASKIN;
 
163
        } else if ((wanted & MASKIN) && !(fd->registered_bands & MASKIN)) {
 
164
                queue(fd->fd, EVFILT_READ, EV_ADD | EV_ENABLE,
 
165
                      0, 0, (void *)fd);
 
166
                fd->registered_bands |= MASKIN;
 
167
        }
 
168
 
 
169
        if ((fd->registered_bands & MASKOUT) && !(wanted & MASKOUT)) {
 
170
                queue(fd->fd, EVFILT_WRITE, EV_DELETE, 0, 0, (void *)fd);
 
171
                fd->registered_bands &= ~MASKOUT;
 
172
        } else if ((wanted & MASKOUT) && !(fd->registered_bands & MASKOUT)) {
 
173
                queue(fd->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE,
 
174
                      0, 0, (void *)fd);
 
175
                fd->registered_bands |= MASKOUT;
 
176
        }
 
177
        if (wanted & MASKERR) {
 
178
                /* NOTE: kqueue doesn't support POLLERR-like interface, but
 
179
                 * we need to set it here, as otherwise we run into a failed
 
180
                 * assertion later on in the ivykis core.
 
181
                 */
 
182
 
 
183
                fd->registered_bands |= MASKERR;
 
184
        }
 
185
}
 
186
 
 
187
static void iv_kqueue_deinit(void)
 
188
{
 
189
        free(upload_queue);
 
190
        close(kqueue_fd);
 
191
}
 
192
 
 
193
static int iv_kqueue_pollable(int fd)
 
194
{
 
195
        struct timespec to = { 0, 0 };
 
196
        struct kevent kev;
 
197
        int ret;
 
198
 
 
199
        EV_SET(&kev, fd, EVFILT_READ, EV_ADD, 0, 0, &fd);
 
200
 
 
201
        do {
 
202
                ret = kevent(kqueue_fd, &kev, 1,
 
203
                             NULL, 0, &to);
 
204
        } while (ret < 0 && errno == EINTR);
 
205
 
 
206
        if (ret < 0 && errno == ENODEV)
 
207
                return 0;
 
208
        if (ret >= 0) {
 
209
                EV_SET(&kev, fd, EVFILT_READ, EV_DELETE, 0, 0, &fd);
 
210
 
 
211
                do {
 
212
                        ret = kevent(kqueue_fd, &kev, 1,
 
213
                                     NULL, 0, &to);
 
214
                } while (ret < 0 && errno == EINTR);
 
215
 
 
216
                if (ret < 0) {
 
217
                        fprintf(stderr, "iv_kqueue_pollable: got error %d[%s]",
 
218
                               errno, strerror(errno));
 
219
                        abort();
 
220
                }
 
221
        }
 
222
        return 1;
 
223
}
 
224
 
 
225
struct iv_poll_method iv_method_kqueue = {
 
226
        .name           = "kqueue",
 
227
        .init           = iv_kqueue_init,
 
228
        .poll           = iv_kqueue_poll,
 
229
        .unregister_fd  = iv_kqueue_unregister_fd,
 
230
        .notify_fd      = iv_kqueue_notify_fd,
 
231
        .pollable       = iv_kqueue_pollable,
 
232
        .deinit         = iv_kqueue_deinit,
 
233
};