Index: trunk/willow/src/include/wconfig.h |
— | — | @@ -32,6 +32,10 @@ |
33 | 33 | int port; |
34 | 34 | int group; |
35 | 35 | wnet::socket *sock; |
| 36 | + |
| 37 | + ~listener() { |
| 38 | + delete sock; |
| 39 | + } |
36 | 40 | }; |
37 | 41 | extern vector<listener *> listeners; |
38 | 42 | extern map<wsocket *, int> lsn2group; |
Index: trunk/willow/src/include/wthread.h |
— | — | @@ -223,11 +223,13 @@ |
224 | 224 | return ~v1.v; |
225 | 225 | } |
226 | 226 | |
227 | | -template<typename T> |
| 227 | +void tss_null_dtor(void *); |
| 228 | + |
| 229 | +template<typename T, void dtor (void *) = tss_null_dtor> |
228 | 230 | struct tss { |
229 | 231 | mutable pthread_key_t _key; |
230 | 232 | tss() { |
231 | | - pthread_key_create(&_key, NULL); |
| 233 | + pthread_key_create(&_key, dtor); |
232 | 234 | } |
233 | 235 | T const& operator* (void) const { |
234 | 236 | return *(T *)pthread_getspecific(_key); |
Index: trunk/willow/src/include/ptalloc.h |
— | — | @@ -47,13 +47,24 @@ |
48 | 48 | }; |
49 | 49 | |
50 | 50 | struct pttsswrap { |
| 51 | + static void pttsswrapdtor(void *p) { |
| 52 | + pta_block **pt = (pta_block **)p, *n = *pt, *o; |
| 53 | + while (o = n) { |
| 54 | + n = n->next; |
| 55 | + free(o); |
| 56 | + } |
| 57 | + delete pt; |
| 58 | + } |
| 59 | + |
51 | 60 | pttsswrap() { |
52 | | - pthread_key_create(&key, NULL); |
| 61 | + pthread_key_create(&key, pttsswrapdtor); |
53 | 62 | } |
54 | 63 | pthread_key_t key; |
55 | 64 | }; |
56 | 65 | |
57 | | -extern tss<vector<pta_block *> > ptfreelist; |
| 66 | +void ptdealloc(void *); |
| 67 | + |
| 68 | +extern tss<vector<pta_block *>, ptdealloc> ptfreelist; |
58 | 69 | extern pttsswrap pttssw; |
59 | 70 | |
60 | 71 | template<typename T> |
— | — | @@ -106,6 +117,7 @@ |
107 | 118 | size_t sz = sizeof(T) * n; |
108 | 119 | int exp = ilog2(sz) + 1; |
109 | 120 | void *ret; |
| 121 | + |
110 | 122 | if (!ptfreelist) |
111 | 123 | ptfreelist = new vector<pta_block *>; |
112 | 124 | vector<pta_block *> &fl = *ptfreelist; |
— | — | @@ -119,7 +131,7 @@ |
120 | 132 | return (pointer) ret; |
121 | 133 | } |
122 | 134 | /* no, need a new block */ |
123 | | - ret = new char[2 << (exp - 1)]; |
| 135 | + ret = new char[2 << exp]; |
124 | 136 | return (pointer) ret; |
125 | 137 | } |
126 | 138 | |
— | — | @@ -127,6 +139,7 @@ |
128 | 140 | size_t sz = sizeof(T) * n; |
129 | 141 | int exp = ilog2(sz) + 1; |
130 | 142 | pta_block *ptb = get_ptb(); |
| 143 | + |
131 | 144 | if (!ptfreelist) |
132 | 145 | ptfreelist = new vector<pta_block *>; |
133 | 146 | vector<pta_block *> &fl = *ptfreelist; |
Index: trunk/willow/src/include/flalloc.h |
— | — | @@ -18,9 +18,20 @@ |
19 | 19 | #include "wthread.h" |
20 | 20 | |
21 | 21 | template<typename T> |
| 22 | +void |
| 23 | +flalloc_dtor(void *p) |
| 24 | +{ |
| 25 | +T *n = (T *)p, *o; |
| 26 | + while (o = n) { |
| 27 | + n = n->_freelist_next; |
| 28 | + ::operator delete(o); |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +template<typename T> |
22 | 33 | struct freelist_allocator { |
23 | 34 | T *_freelist_next; |
24 | | -static tss<T> _freelist; |
| 35 | +static tss<T, flalloc_dtor<T> > _freelist; |
25 | 36 | |
26 | 37 | void *operator new(std::size_t size) { |
27 | 38 | if (_freelist) { |
— | — | @@ -46,6 +57,6 @@ |
47 | 58 | }; |
48 | 59 | |
49 | 60 | template<typename T> |
50 | | -tss<T> freelist_allocator<T>::_freelist; |
| 61 | +tss<T, flalloc_dtor<T> > freelist_allocator<T>::_freelist; |
51 | 62 | |
52 | 63 | #endif |
Index: trunk/willow/src/include/willow.h |
— | — | @@ -183,6 +183,12 @@ |
184 | 184 | bool operator!= (basic_imstring const &) const; |
185 | 185 | |
186 | 186 | private: |
| 187 | + template<typename charT2, typename allocator2> |
| 188 | + basic_imstring(basic_imstring<charT2, allocator2> const &); |
| 189 | + template<typename charT2, typename allocator2> |
| 190 | + basic_imstring & |
| 191 | + operator=(basic_imstring<charT2, allocator2> const &); |
| 192 | + |
187 | 193 | charT *_buf, *_end; |
188 | 194 | size_type _len; |
189 | 195 | |
— | — | @@ -200,6 +206,8 @@ |
201 | 207 | |
202 | 208 | template<typename charT, typename allocator> |
203 | 209 | basic_imstring<charT, allocator>::basic_imstring(charT const *str) |
| 210 | + : _buf(NULL) |
| 211 | + , _len(0) |
204 | 212 | { |
205 | 213 | reserve(strlen(str)); |
206 | 214 | _end = _buf + _len; |
— | — | @@ -208,6 +216,8 @@ |
209 | 217 | |
210 | 218 | template<typename charT, typename allocator> |
211 | 219 | basic_imstring<charT, allocator>::basic_imstring(charT const *str, size_type len) |
| 220 | + : _buf(NULL) |
| 221 | + , _len(0) |
212 | 222 | { |
213 | 223 | reserve(len); |
214 | 224 | _end = _buf + _len; |
— | — | @@ -217,6 +227,8 @@ |
218 | 228 | |
219 | 229 | template<typename charT, typename allocator> |
220 | 230 | basic_imstring<charT, allocator>::basic_imstring(basic_imstring const &o) |
| 231 | + : _buf(NULL) |
| 232 | + , _len(0) |
221 | 233 | { |
222 | 234 | reserve(o._len); |
223 | 235 | _end = _buf + _len; |
— | — | @@ -260,7 +272,18 @@ |
261 | 273 | if (this == &o) |
262 | 274 | return *this; |
263 | 275 | |
264 | | - _alloc.deallocate(_buf, _len); |
| 276 | + if (_buf) { |
| 277 | + _alloc.deallocate(_buf, _len); |
| 278 | + _buf = NULL; |
| 279 | + _len = 0; |
| 280 | + } |
| 281 | + |
| 282 | + if (!o._buf) { |
| 283 | + _buf = 0; |
| 284 | + _len = 0; |
| 285 | + return *this; |
| 286 | + } |
| 287 | + |
265 | 288 | reserve(o._len); |
266 | 289 | _end = _buf + _len; |
267 | 290 | memcpy(_buf, o._buf, _len + 1); |
— | — | @@ -271,6 +294,8 @@ |
272 | 295 | template<typename Sallocator> |
273 | 296 | basic_imstring<charT, allocator>::basic_imstring( |
274 | 297 | basic_string<charT, char_traits<charT>, Sallocator> const &s) |
| 298 | + : _buf(NULL) |
| 299 | + , _len(0) |
275 | 300 | { |
276 | 301 | reserve(s.size()); |
277 | 302 | _end = _buf + _len; |
— | — | @@ -284,6 +309,8 @@ |
285 | 310 | basic_imstring<charT, allocator>::reserve( |
286 | 311 | basic_imstring<charT, allocator>::size_type s) |
287 | 312 | { |
| 313 | + if (_buf) |
| 314 | + _alloc.deallocate(_buf, _len); |
288 | 315 | _buf = _alloc.allocate(s + 1); |
289 | 316 | _len = s; |
290 | 317 | _end = _buf; |
Index: trunk/willow/src/include/wnet.h |
— | — | @@ -47,7 +47,7 @@ |
48 | 48 | #include "willow.h" |
49 | 49 | #include "polycaller.h" |
50 | 50 | |
51 | | -struct client_data; |
| 51 | +extern bool wnet_exit; |
52 | 52 | |
53 | 53 | namespace wnet { |
54 | 54 | struct addrlist; |
— | — | @@ -145,7 +145,6 @@ |
146 | 146 | extern char current_time_str[]; |
147 | 147 | extern char current_time_short[]; |
148 | 148 | extern time_t current_time; |
149 | | -extern int wnet_exit; |
150 | 149 | |
151 | 150 | void wnet_add_accept_wakeup (wnet::socket *); |
152 | 151 | void wnet_set_time (void); |
Index: trunk/willow/src/include/wbackend.h |
— | — | @@ -96,6 +96,7 @@ |
97 | 97 | |
98 | 98 | struct backend_pool { |
99 | 99 | backend_pool(string const &name, lb_type); |
| 100 | + ~backend_pool(); |
100 | 101 | |
101 | 102 | void add (string const &, int, int); |
102 | 103 | backend_list *get_list (imstring const & url, imstring const &host); |
Index: trunk/willow/src/include/whttp_header.h |
— | — | @@ -186,6 +186,7 @@ |
187 | 187 | , _http_reqtype(REQTYPE_INVALID) |
188 | 188 | , _no_keepalive(false) |
189 | 189 | , _force_keepalive(false) |
| 190 | + , _follow_redirect(false) |
190 | 191 | , _eof(false) |
191 | 192 | { |
192 | 193 | _flags.f_chunked = 0; |
Index: trunk/willow/src/willow/wconfig.cc |
— | — | @@ -443,6 +443,7 @@ |
444 | 444 | config.keepalive_max = 0; |
445 | 445 | config.max_redirects = 1; |
446 | 446 | config.use_dio = false; |
| 447 | + config.x_follow = false; |
447 | 448 | |
448 | 449 | conf.set(*t); |
449 | 450 | whttp_reconfigure(); |
Index: trunk/willow/src/willow/whttp.cc |
— | — | @@ -172,6 +172,9 @@ |
173 | 173 | imstring _request_host; |
174 | 174 | imstring _request_path; |
175 | 175 | int _nredir; |
| 176 | + |
| 177 | +private: |
| 178 | + httpcllr(const httpcllr &); |
176 | 179 | }; |
177 | 180 | |
178 | 181 | httpcllr::httpcllr(wsocket *s, int gr) |
— | — | @@ -673,10 +676,13 @@ |
674 | 677 | % config.nthreads); |
675 | 678 | for (int i = 0; i < config.nthreads; ++i) { |
676 | 679 | http_thread *t = new http_thread; |
| 680 | + pthread_attr_t attr; |
| 681 | + pthread_attr_init(&attr); |
| 682 | + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); |
677 | 683 | t->sv = wnet::socket::socketpair(st_dgram); |
678 | 684 | wnet_add_accept_wakeup(t->sv.first); |
679 | 685 | threads.push_back(t); |
680 | | - pthread_create(&t->thr, NULL, client_thread, t); |
| 686 | + pthread_create(&t->thr, &attr, client_thread, t); |
681 | 687 | } |
682 | 688 | whttp_header_init(); |
683 | 689 | } |
— | — | @@ -731,13 +737,20 @@ |
732 | 738 | sv.second->readback(polycaller<wsocket *, int>(*this, |
733 | 739 | &http_thread::accept_wakeup), 0); |
734 | 740 | event_base_loop(evb, 0); |
735 | | - wlog(WLOG_ERROR, format("event_base_loop: %e")); |
736 | | - exit(1); |
| 741 | + delete merge_ev; |
| 742 | + delete stats.tcur; |
| 743 | + return; |
737 | 744 | } |
738 | 745 | |
739 | 746 | static void |
740 | 747 | stats_merge(int, short, void *) |
741 | 748 | { |
| 749 | +timeval tv = {0, 0}; |
| 750 | + if (wnet_exit) { |
| 751 | + event_base_loopexit(evb, &tv); |
| 752 | + return; |
| 753 | + } |
| 754 | + |
742 | 755 | { HOLDING(stats.cur_lock); |
743 | 756 | stats.cur.n_httpreq_ok += stats.tcur->n_httpreq_ok; |
744 | 757 | stats.tcur->n_httpreq_ok = 0; |
Index: trunk/willow/src/willow/wnet.cc |
— | — | @@ -56,7 +56,7 @@ |
57 | 57 | |
58 | 58 | static void secondly_sched(void); |
59 | 59 | |
60 | | -int wnet_exit; |
| 60 | +bool wnet_exit; |
61 | 61 | vector<wsocket *> awaks; |
62 | 62 | int cawak; |
63 | 63 | |
— | — | @@ -583,12 +583,17 @@ |
584 | 584 | void |
585 | 585 | sig_exit(int sig, short what, void *d) |
586 | 586 | { |
587 | | - exit(0); |
| 587 | + wnet_exit = true; |
588 | 588 | } |
589 | 589 | |
590 | 590 | void |
591 | 591 | ioloop_t::run(void) |
592 | 592 | { |
593 | | - event_base_loop(evb, 0); |
594 | | - perror("event_base_loop"); |
| 593 | + while (!wnet_exit) { |
| 594 | + event_base_loop(evb, EVLOOP_ONCE); |
| 595 | + } |
| 596 | + |
| 597 | +size_t i; |
| 598 | + for (i = 0; i < listeners.size(); ++i) |
| 599 | + delete listeners[i]; |
595 | 600 | } |
Index: trunk/willow/src/willow/willow.cc |
— | — | @@ -34,18 +34,38 @@ |
35 | 35 | |
36 | 36 | static const char *progname; |
37 | 37 | |
38 | | -tss<vector<pta_block *> > ptfreelist; |
| 38 | +tss<vector<pta_block *>, ptdealloc> ptfreelist; |
39 | 39 | pttsswrap pttssw; |
| 40 | +event checkexit_ev; |
| 41 | +timeval checkexit_tv; |
40 | 42 | |
41 | 43 | #define min(x,y) ((x) < (y) ? (x) : (y)) |
42 | 44 | |
43 | | -static void |
44 | | -sig_exit(int) |
| 45 | +static void checkexit_sched(void); |
| 46 | + |
| 47 | +static void |
| 48 | +checkexit_update(int, short, void *) |
45 | 49 | { |
46 | | - wnet_exit = 1; |
| 50 | +timeval tv = {0, 0}; |
| 51 | + if (wnet_exit) { |
| 52 | + event_del(&checkexit_ev); |
| 53 | + event_base_loopexit(evb, &tv); |
| 54 | + return; |
| 55 | + } |
| 56 | + checkexit_sched(); |
47 | 57 | } |
48 | 58 | |
49 | 59 | static void |
| 60 | +checkexit_sched(void) |
| 61 | +{ |
| 62 | + checkexit_tv.tv_usec = 0; |
| 63 | + checkexit_tv.tv_sec = 1; |
| 64 | + evtimer_set(&checkexit_ev, checkexit_update, NULL); |
| 65 | + event_base_set(evb, &checkexit_ev); |
| 66 | + event_add(&checkexit_ev, &checkexit_tv); |
| 67 | +} |
| 68 | + |
| 69 | +static void |
50 | 70 | usage(void) |
51 | 71 | { |
52 | 72 | fprintf(stderr, "usage: %s [-hfzv] [-D cond[=value]]\n" |
— | — | @@ -59,6 +79,28 @@ |
60 | 80 | , progname); |
61 | 81 | } |
62 | 82 | |
| 83 | +void |
| 84 | +tss_null_dtor(void *) |
| 85 | +{ |
| 86 | +} |
| 87 | + |
| 88 | +void |
| 89 | +ptdealloc(void *p) |
| 90 | +{ |
| 91 | +vector<pta_block *> *v = (vector<pta_block *> *)p; |
| 92 | +std::cout<<"ptdealloc\n"; |
| 93 | + for (vector<pta_block *>::iterator it = v->begin(), end = v->end(); |
| 94 | + it != end; ++it) { |
| 95 | + pta_block *n = *it, *o; |
| 96 | + while (o = n) { |
| 97 | + n = n->next; |
| 98 | + delete [] (char *)o->addr; |
| 99 | + free(o); |
| 100 | + } |
| 101 | + } |
| 102 | + delete v; |
| 103 | +} |
| 104 | + |
63 | 105 | int |
64 | 106 | main(int argc, char *argv[]) |
65 | 107 | { |
— | — | @@ -152,23 +194,23 @@ |
153 | 195 | |
154 | 196 | make_event_base(); |
155 | 197 | ioloop = new ioloop_t; |
| 198 | + checkexit_sched(); |
156 | 199 | whttp_init(); |
157 | 200 | wcache_init(1); |
158 | 201 | stats_init(); |
159 | 202 | |
160 | | - (void)signal(SIGINT, sig_exit); |
161 | | - (void)signal(SIGTERM, sig_exit); |
162 | | - |
163 | 203 | wlog(WLOG_NOTICE, "running"); |
164 | 204 | |
165 | 205 | if (!config.foreground) |
166 | 206 | daemon(0, 0); |
167 | 207 | |
168 | 208 | ioloop->run(); |
| 209 | + wlog(WLOG_NOTICE, "shutting down"); |
169 | 210 | wlog_close(); |
170 | 211 | wcache_shutdown(); |
171 | 212 | whttp_shutdown(); |
172 | | - |
| 213 | + |
| 214 | + pthread_exit(NULL); |
173 | 215 | return EXIT_SUCCESS; |
174 | 216 | } |
175 | 217 | |
Index: trunk/willow/src/willow/wbackend.cc |
— | — | @@ -85,6 +85,7 @@ |
86 | 86 | % addr % it->straddr()); |
87 | 87 | } |
88 | 88 | |
| 89 | + delete list; |
89 | 90 | _carp_calc(); |
90 | 91 | } |
91 | 92 | |
— | — | @@ -190,6 +191,12 @@ |
191 | 192 | _carp_recalc(url, host, lbt); |
192 | 193 | } |
193 | 194 | |
| 195 | +backend_pool::~backend_pool(void) |
| 196 | +{ |
| 197 | + for (int i = 0; i < backends.size(); ++i) |
| 198 | + delete backends[i]; |
| 199 | +} |
| 200 | + |
194 | 201 | backend_list * |
195 | 202 | backend_pool::get_list(imstring const &url, imstring const &host) |
196 | 203 | { |
Index: trunk/willow/src/willow/wcache.cc |
— | — | @@ -275,6 +275,8 @@ |
276 | 276 | int stlen; |
277 | 277 | struct cache_object *obj; |
278 | 278 | |
| 279 | + if (!config.caches) |
| 280 | + return; |
279 | 281 | stlen = strlen(config.caches[0].dir) + 1 + 5 + 1; |
280 | 282 | if ((stpath = (char *)wmalloc(stlen)) == NULL) |
281 | 283 | outofmemory(); |