src/server/daemon/event_linux.c

Wed, 05 Jun 2024 22:42:52 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 05 Jun 2024 22:42:52 +0200
changeset 538
f9a7b5c76208
parent 537
ad44e72fbf50
permissions
-rw-r--r--

replace EWOULDBLOCK with EAGAIN

41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
1 /*
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
3 *
44
3da1f7b6847f added some error messages
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 43
diff changeset
4 * Copyright 2013 Olaf Wintermann. All rights reserved.
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
5 *
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
6 * Redistribution and use in source and binary forms, with or without
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
7 * modification, are permitted provided that the following conditions are met:
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
8 *
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
9 * 1. Redistributions of source code must retain the above copyright
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
10 * notice, this list of conditions and the following disclaimer.
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
11 *
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
12 * 2. Redistributions in binary form must reproduce the above copyright
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
13 * notice, this list of conditions and the following disclaimer in the
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
14 * documentation and/or other materials provided with the distribution.
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
15 *
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
26 * POSSIBILITY OF SUCH DAMAGE.
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
27 */
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
28
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
29 #include <stdio.h>
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
30 #include <stdlib.h>
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
31 #include <errno.h>
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
32 #include <sys/epoll.h>
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
33 #include <sys/eventfd.h>
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
34
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
35 #include "../util/systhr.h"
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
36 #include "../util/atomic.h"
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
37
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
38 #include "../util/io.h"
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
39
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
40 #include "event.h"
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
41 #include "event_linux.h"
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
42
531
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
43 #include "httprequest.h"
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
44
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
45
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
46 EVHandler* evhandler_create(EventHandlerConfig *cfg) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
47 EVHandler *ev = malloc(sizeof(EVHandler));
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
48 ev->current = 0;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
49 ev->instances = calloc(cfg->nthreads, sizeof(void*));
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
50 ev->numins = cfg->nthreads;
443
ef3c8a0e1fee improve daemon startup
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 193
diff changeset
51
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
52 for(int i=0;i<cfg->nthreads;i++) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
53 EventHandler *handler = malloc(sizeof(EventHandler));
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
54 ev->instances[i] = handler;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
55
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
56 handler->ep = epoll_create(64);
443
ef3c8a0e1fee improve daemon startup
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 193
diff changeset
57 if(handler->ep < 0) {
ef3c8a0e1fee improve daemon startup
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 193
diff changeset
58 log_ereport(LOG_FAILURE, "evhandler_create: epoll_create: %s", strerror(errno));
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
59 return NULL;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
60 }
192
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
61
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
62 int eventpipe[2];
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
63 if(pipe(eventpipe)) {
443
ef3c8a0e1fee improve daemon startup
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 193
diff changeset
64 log_ereport(LOG_FAILURE, "evhandler_create: pipe: %s", strerror(errno));
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
65 return NULL;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
66 }
192
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
67 handler->eventin = eventpipe[0];
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
68 handler->eventout = eventpipe[1];
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
69
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
70 struct epoll_event epev;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
71 epev.events = EPOLLIN | EPOLLET; // input event, edge triggered
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
72 epev.data.ptr = NULL;
192
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
73 if(epoll_ctl(handler->ep, EPOLL_CTL_ADD, handler->eventin, &epev)) {
474
eb7640c59e9b fix broken log_ereport call
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 443
diff changeset
74 log_ereport(LOG_FAILURE, "evhandler_create: epoll_ctl: %s", strerror(errno));
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
75 return NULL;
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
76 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
77
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
78 SYS_THREAD t = systhread_start(
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
79 0,
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
80 0,
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
81 (thrstartfunc)ev_handle_events,
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
82 handler);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
83 systhread_detach(t);
443
ef3c8a0e1fee improve daemon startup
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 193
diff changeset
84 }
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
85
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
86 return ev;
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
87 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
88
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
89 void ev_handle_events(EventHandler *ev) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
90 int ep = ev->ep;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
91
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
92 struct epoll_event events[EV_MAX_EVENTS];
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
93 Event* finished[EV_MAX_EVENTS];
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
94
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
95 for(;;) {
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
96 /* wait for events */
48
37a512d7b8f6 fixed some memory leaks
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 46
diff changeset
97 int ret = epoll_wait(ep, events, 16, 100000);
126
631aaa01b2b5 fixes chunked transfer encoding
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 79
diff changeset
98 if(ret == -1 && errno != EINTR) {
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
99 log_ereport(LOG_FAILURE, "epoll_wait failed: %s", strerror(errno));
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
100 continue;
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
101 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
102
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
103 int numfinished = 0;
531
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
104 ev->numret = 0;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
105 for(int i=0;i<ret;i++) {
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
106 Event *event = events[i].data.ptr;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
107 if(!event) {
192
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
108 char ebuf[sizeof(Event*)];
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
109 int ebufpos = 0;
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
110 char *b = ebuf;
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
111 while(ebufpos < sizeof(Event*)) {
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
112 ssize_t r = read(ev->eventin, b + ebufpos, sizeof(Event*)-ebufpos);
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
113 if(r < 0) {
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
114 break;
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
115 }
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
116 ebufpos += r;
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
117 }
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
118 if(ebufpos == sizeof(Event*)) {
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
119 intptr_t *p = (intptr_t*)b;
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
120 *(&event) = (Event*)*p;
533
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
121 /*
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
122 if(event->fn) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
123 if(!event->fn(ev, event) && event->finish) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
124 event->finish(ev, event);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
125 }
533
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
126 }*/
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
127 } else {
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
128 continue; // should not happen
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
129 }
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
130 }
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
131
2d6099ba2a7c simplify ev_handle_events on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 531
diff changeset
132 if(event->fn) {
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
133 int saved_ev = event->events;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
134 if(!event->fn(ev, event)) {
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
135 // event fn returned 0 -> remove event from epoll
43
8ac56edb4e94 fixed solaris build
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 41
diff changeset
136 if(epoll_ctl(ep, EPOLL_CTL_DEL, event->object, NULL)) {
152
8b85c5face66 improves sessionhandler logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
137 event->error = 1;
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
138 log_ereport(
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
139 LOG_FAILURE,
152
8b85c5face66 improves sessionhandler logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
140 "epoll_ctl failed: fd: %d error: %s",
8b85c5face66 improves sessionhandler logging
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 133
diff changeset
141 event->object,
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
142 strerror(errno));
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
143 }
46
636e05eb48f6 cleaning up resources after requests
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 44
diff changeset
144
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
145 // if set, remember this event and
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
146 // execute event->finish later
46
636e05eb48f6 cleaning up resources after requests
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 44
diff changeset
147 if(event->finish) {
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
148 finished[numfinished++] = event;
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
149 //event->finish(ev, event);
46
636e05eb48f6 cleaning up resources after requests
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 44
diff changeset
150 }
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
151 } else {
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
152 if(saved_ev != event->events) {
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
153 // event type changed
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
154 struct epoll_event epev;
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
155 epev.events = EPOLLET;
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
156 epev.data.ptr = event;
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
157
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
158 // adjust epoll events
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
159 epev.events = ev_convert2sys_events(event->events);
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
160
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
161 if(epoll_ctl(ep, EPOLL_CTL_MOD, event->object, &epev)) {
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
162 log_ereport(
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
163 LOG_FAILURE,
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
164 "epoll_wait failed: %s",
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
165 strerror(errno));
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
166 }
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
167 }
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
168 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
169 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
170 }
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
171 // call event finish handlers
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
172 for(int i=0;i<numfinished;i++) {
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
173 Event *event = finished[i];
537
ad44e72fbf50 add extra nullptr check in the event loop to handle the case when the finish ptr is set to NULL after it was already scheduled
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 533
diff changeset
174 // check again if the finish callback is set
ad44e72fbf50 add extra nullptr check in the event loop to handle the case when the finish ptr is set to NULL after it was already scheduled
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 533
diff changeset
175 if(finished[i]->finish) {
ad44e72fbf50 add extra nullptr check in the event loop to handle the case when the finish ptr is set to NULL after it was already scheduled
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 533
diff changeset
176 finished[i]->finish(ev, event);
ad44e72fbf50 add extra nullptr check in the event loop to handle the case when the finish ptr is set to NULL after it was already scheduled
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 533
diff changeset
177 }
529
cd606400f0ba change execution order of event handler and event finish functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 474
diff changeset
178 }
531
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
179 // execute return calls
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
180 for(int i=0;i<ev->numret;i++) {
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
181 EVReturn ret = ev->fnreturn[i];
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
182 nsapi_saf_return(ret.sn, ret.rq, ret.ret);
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
183 }
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
184 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
185 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
186
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
187 int ev_convert2sys_events(int events) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
188 int e = EPOLLET;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
189 if((events & EVENT_POLLIN) == EVENT_POLLIN) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
190 e |= EPOLLIN;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
191 }
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
192 if((events & EVENT_POLLOUT) == EVENT_POLLOUT) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
193 e |= EPOLLOUT;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
194 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
195 return e;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
196 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
197
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
198 int ev_pollin(EventHandler *h, int fd, Event *event) {
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
199 event->object = (intptr_t)fd;
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
200 event->events = EVENT_POLLIN;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
201 struct epoll_event epev;
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
202 epev.events = EPOLLIN | EPOLLET; // input event, edge triggered
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
203 epev.data.ptr = event;
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
204 return epoll_ctl(h->ep, EPOLL_CTL_ADD, fd, &epev);
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
205 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
206
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
207 int ev_pollout(EventHandler *h, int fd, Event *event) {
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
208 event->object = (intptr_t)fd;
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
209 event->events = EVENT_POLLOUT;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
210 struct epoll_event epev;
133
87b405d61f64 improves event handler and ssl error handling
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 126
diff changeset
211 epev.events = EPOLLOUT | EPOLLET; // input event, edge triggered
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
212 epev.data.ptr = event;
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
213 return epoll_ctl(h->ep, EPOLL_CTL_ADD, fd, &epev);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
214 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
215
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
216 int ev_remove_poll(EventHandler *h, int fd) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
217 return epoll_ctl(h->ep, EPOLL_CTL_DEL, fd, NULL);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
218 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
219
187
4384bfbb7e26 adds platform independent aio functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 185
diff changeset
220 int event_send(EventHandler *h, Event *event) {
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
221 event->object = 0;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
222 event->events = 0;
192
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
223 ssize_t r = write(h->eventout, &event, sizeof(Event*));
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
224 if(r < sizeof(Event*)) {
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
225 log_ereport(LOG_FAILURE, "failed to send event: %s", strerror(errno));
6a145e13d933 replaces eventfd with pipe and closes aio branch
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 187
diff changeset
226 }
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
227 return r > 0 ? 0 : 1;
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
228 }
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
229
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
230 // TODO: remove this fake aio
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
231 int ev_aioread(int fd, aiocb_s *cb) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
232 ssize_t result = pread(fd, cb->buf, cb->nbytes, cb->offset);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
233 cb->result = result;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
234 if(result < 0) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
235 cb->result_errno = errno;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
236 }
187
4384bfbb7e26 adds platform independent aio functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 185
diff changeset
237 return event_send(cb->evhandler, cb->event);
41
bb7a1f5a8b48 added Linux support
Olaf Wintermann <olaf.wintermann@gmail.com>
parents:
diff changeset
238 }
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
239
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
240 int ev_aiowrite(int fd, aiocb_s *cb) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
241 ssize_t result = pwrite(fd, cb->buf, cb->nbytes, cb->offset);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
242 cb->result = result;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
243 if(result < 0) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
244 cb->result_errno = errno;
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
245 }
187
4384bfbb7e26 adds platform independent aio functions
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 185
diff changeset
246 return event_send(cb->evhandler, cb->event);
185
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
247 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
248
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
249
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
250 int event_pollin(EventHandler *ev, SYS_NETFD fd, Event *event) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
251 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_IN, event);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
252 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
253
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
254 int event_pollout(EventHandler *ev, SYS_NETFD fd, Event *event) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
255 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_OUT, event);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
256 }
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
257
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
258 int event_removepoll(EventHandler *ev, SYS_NETFD fd) {
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
259 return ((IOStream*)fd)->poll(fd, ev, IO_POLL_NONE, NULL);
b4d7ccf4e06d implements new event handler and aio on linux
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 152
diff changeset
260 }
531
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
261
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
262
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
263 void ev_saf_return(EventHandler *h, Session *sn, Request *rq, int ret) {
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
264 h->fnreturn[h->numret++] = (EVReturn){ sn, rq, ret };
9b15b1f72bef change nsapi_function_return behavior: move saf return to the end of the event cycle
Olaf Wintermann <olaf.wintermann@gmail.com>
parents: 529
diff changeset
265 }

mercurial