Merge lp:~brianaker/drizzle/memoryleak-fix-json-server into lp:~drizzle-trunk/drizzle/development

Proposed by Brian Aker
Status: Merged
Approved by: Brian Aker
Approved revision: 2364
Merged at revision: 2364
Proposed branch: lp:~brianaker/drizzle/memoryleak-fix-json-server
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 310 lines (+160/-37)
6 files modified
drizzled/drizzled.cc (+1/-1)
drizzled/temporal_format.cc (+5/-0)
drizzled/temporal_format.h (+3/-0)
m4/pandora_have_libcurl.m4 (+8/-4)
plugin/json_server/json_server.cc (+126/-29)
plugin/json_server/plugin.ini (+17/-3)
To merge this branch: bzr merge lp:~brianaker/drizzle/memoryleak-fix-json-server
Reviewer Review Type Date Requested Status
Drizzle Merge Team Pending
Review via email: mp+67770@code.launchpad.net

Description of the change

Fixes two of the valgrind warnings that occur during shutdown.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'drizzled/drizzled.cc'
2--- drizzled/drizzled.cc 2011-06-24 15:25:06 +0000
3+++ drizzled/drizzled.cc 2011-07-12 23:41:40 +0000
4@@ -1422,7 +1422,7 @@
5 if (sys_var_init())
6 return 1;
7 /* Creates static regex matching for temporal values */
8- if (! init_temporal_formats())
9+ if (not init_temporal_formats())
10 return 1;
11
12 if (!(default_charset_info=
13
14=== modified file 'drizzled/temporal_format.cc'
15--- drizzled/temporal_format.cc 2011-06-23 11:06:21 +0000
16+++ drizzled/temporal_format.cc 2011-07-12 23:41:40 +0000
17@@ -66,6 +66,11 @@
18 );
19 }
20
21+TemporalFormat::~TemporalFormat()
22+{
23+ pcre_free(_re);
24+}
25+
26 bool TemporalFormat::matches(const char *data, size_t data_len, Temporal *to)
27 {
28 if (! is_valid())
29
30=== modified file 'drizzled/temporal_format.h'
31--- drizzled/temporal_format.h 2011-03-29 12:45:08 +0000
32+++ drizzled/temporal_format.h 2011-07-12 23:41:40 +0000
33@@ -63,6 +63,9 @@
34 * @param Pattern to use in matching
35 */
36 TemporalFormat(const char *pattern);
37+
38+ ~TemporalFormat();
39+
40 /**
41 * Returns whether the instance is compiled
42 * and contains a valid regular expression.
43
44=== modified file 'm4/pandora_have_libcurl.m4'
45--- m4/pandora_have_libcurl.m4 2011-03-07 16:42:18 +0000
46+++ m4/pandora_have_libcurl.m4 2011-07-12 23:41:40 +0000
47@@ -32,10 +32,14 @@
48 AC_COMPILE_IFELSE([
49 AC_LANG_PROGRAM(
50 [[
51- CURL *handle;
52- handle=curl_easy_init();
53- rv= curl_easy_setopt(curl_handle, CURLOPT_USERNAME, "foo");
54- ]])],
55+ #include <curl/curl.h>
56+ ]],
57+ [[
58+ CURL *curl_handle=curl_easy_init();
59+ CURLcode rv= curl_easy_setopt(curl_handle, CURLOPT_USERNAME, "foo");
60+ (void)rv;
61+ ]])
62+ ],
63 [pandora_cv_curl_have_username=yes],
64 [pandora_cv_curl_have_username=no])
65 ])
66
67=== modified file 'plugin/json_server/json_server.cc'
68--- plugin/json_server/json_server.cc 2011-04-21 07:15:35 +0000
69+++ plugin/json_server/json_server.cc 2011-07-12 23:41:40 +0000
70@@ -20,10 +20,15 @@
71
72
73 #include <config.h>
74+
75+#include <unistd.h>
76+#include <fcntl.h>
77+
78 #include <drizzled/module/module.h>
79 #include <drizzled/module/context.h>
80 #include <drizzled/plugin/plugin.h>
81 #include <drizzled/plugin.h>
82+#include <drizzled/plugin/daemon.h>
83 #include <drizzled/sys_var.h>
84 #include <drizzled/gettext.h>
85 #include <drizzled/error.h>
86@@ -38,7 +43,6 @@
87 #include <drizzled/constrained_value.h>
88 #include <evhttp.h>
89 #include <event.h>
90-#include <pthread.h>
91 #include <drizzled/execute.h>
92 #include <drizzled/sql/result_set.h>
93
94@@ -46,6 +50,10 @@
95 #include <drizzled/plugin/client.h>
96 #include <drizzled/catalog/local.h>
97
98+#include <drizzled/pthread_globals.h>
99+#include <boost/bind.hpp>
100+
101+
102 #include <drizzled/version.h>
103 #include <plugin/json_server/json/json.h>
104
105@@ -59,8 +67,6 @@
106 {
107
108 static port_constraint port;
109-struct event_base *base= NULL;
110-struct evhttp *httpd;
111
112 static in_port_t getPort(void)
113 {
114@@ -222,48 +228,139 @@
115 evhttp_send_reply(req, HTTP_OK, "OK", buf);
116 }
117
118-extern "C" void *libevent_thread(void*);
119-
120-extern "C" void *libevent_thread(void*)
121+static void shutdown_event(int fd, short, void *arg)
122+{
123+ struct event_base *base= (struct event_base *)arg;
124+ event_base_loopbreak(base);
125+ close(fd);
126+}
127+
128+
129+static void run(struct event_base *base)
130 {
131 internal::my_thread_init();
132
133 event_base_dispatch(base);
134- evhttp_free(httpd);
135- return NULL;
136 }
137
138+
139+class JsonServer : public drizzled::plugin::Daemon
140+{
141+private:
142+ JsonServer(const JsonServer &);
143+ JsonServer& operator=(const JsonServer &);
144+
145+ drizzled::thread_ptr json_thread;
146+ in_port_t _port;
147+ struct evhttp *httpd;
148+ struct event_base *base;
149+ int wakeup_fd[2];
150+ struct event wakeup_event;
151+
152+public:
153+ JsonServer(in_port_t port_arg) :
154+ drizzled::plugin::Daemon("JSON Server"),
155+ _port(port_arg),
156+ httpd(NULL),
157+ base(NULL)
158+ { }
159+
160+ bool init()
161+ {
162+ if (pipe(wakeup_fd) < 0)
163+ {
164+ sql_perror("pipe");
165+ return false;
166+ }
167+
168+ int returned_flags;
169+ if ((returned_flags= fcntl(wakeup_fd[0], F_GETFL, 0)) < 0)
170+ {
171+ sql_perror("fcntl:F_GETFL");
172+ return false;
173+ }
174+
175+ if (fcntl(wakeup_fd[0], F_SETFL, returned_flags | O_NONBLOCK) < 0)
176+
177+ {
178+ sql_perror("F_SETFL");
179+ return false;
180+ }
181+
182+ if ((base= event_init()) == NULL)
183+ {
184+ sql_perror("event_init()");
185+ return false;
186+ }
187+
188+ if ((httpd= evhttp_new(base)) == NULL)
189+ {
190+ sql_perror("evhttp_new()");
191+ return false;
192+ }
193+
194+
195+ if ((evhttp_bind_socket(httpd, "0.0.0.0", getPort())) == -1)
196+ {
197+ sql_perror("evhttp_bind_socket()");
198+ return false;
199+ }
200+
201+ evhttp_set_cb(httpd, "/", process_root_request, NULL);
202+ evhttp_set_cb(httpd, "/0.1/version", process_api01_version_req, NULL);
203+ evhttp_set_cb(httpd, "/0.1/sql", process_api01_sql_req, NULL);
204+ evhttp_set_gencb(httpd, process_request, NULL);
205+
206+ event_set(&wakeup_event, wakeup_fd[0], EV_READ | EV_PERSIST, shutdown_event, base);
207+ event_base_set(base, &wakeup_event);
208+ if (event_add(&wakeup_event, NULL) < 0)
209+ {
210+ sql_perror("event_add");
211+ return false;
212+ }
213+
214+ json_thread.reset(new boost::thread((boost::bind(&run, base))));
215+
216+ if (not json_thread)
217+ return false;
218+
219+ return true;
220+ }
221+
222+ ~JsonServer()
223+ {
224+ // If we can't write(), we will just muddle our way through the shutdown
225+ char buffer[1];
226+ buffer[0]= 4;
227+ if ((write(wakeup_fd[1], &buffer, 1)) == 1)
228+ {
229+ json_thread->join();
230+ evhttp_free(httpd);
231+ event_base_free(base);
232+ }
233+ }
234+};
235+
236 static int json_server_init(drizzled::module::Context &context)
237 {
238 context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
239
240- base= event_init();
241- httpd= evhttp_new(base);
242- if (httpd == NULL)
243- return -1;
244-
245- int r= evhttp_bind_socket(httpd, "0.0.0.0", getPort());
246-
247- if (r != 0)
248+ JsonServer *server;
249+ context.add(server= new JsonServer(port));
250+
251+ if (server and not server->init())
252+ {
253 return -2;
254-
255- evhttp_set_cb(httpd, "/", process_root_request, NULL);
256- evhttp_set_cb(httpd, "/0.1/version", process_api01_version_req, NULL);
257- evhttp_set_cb(httpd, "/0.1/sql", process_api01_sql_req, NULL);
258- evhttp_set_gencb(httpd, process_request, NULL);
259-
260- pthread_t libevent_loop_thread;
261-
262- pthread_create(&libevent_loop_thread, NULL, libevent_thread, NULL);
263-
264- return 0;
265+ }
266+
267+ return bool(server) ? 0 : 1;
268 }
269
270 static void init_options(drizzled::module::option_context &context)
271 {
272 context("port",
273- po::value<port_constraint>(&port)->default_value(80),
274- _("Port number to use for connection or 0 for default (port 80) "));
275+ po::value<port_constraint>(&port)->default_value(8086),
276+ _("Port number to use for connection or 0 for default (port 8086) "));
277 }
278
279 } /* namespace json_server */
280
281=== modified file 'plugin/json_server/plugin.ini'
282--- plugin/json_server/plugin.ini 2011-05-02 07:45:56 +0000
283+++ plugin/json_server/plugin.ini 2011-07-12 23:41:40 +0000
284@@ -4,9 +4,23 @@
285 version=0.1
286 author=Stewart Smith
287 license=PLUGIN_LICENSE_GPL
288-headers= json/autolink.h json/config.h json/features.h json/forwards.h json/json_batchallocator.h json/json.h json/reader.h json/value.h json/writer.h json/json_internalarray.inl json/json_internalmap.inl json/json_valueiterator.inl
289+headers=
290+ json/autolink.h
291+ json/config.h
292+ json/features.h
293+ json/forwards.h
294+ json/json_batchallocator.h
295+ json/json.h
296+ json/reader.h
297+ json/value.h
298+ json/writer.h
299+ json/json_internalarray.inl
300+ json/json_internalmap.inl
301+ json/json_valueiterator.inl
302 sources=
303- json_server.cc json/json_reader.cpp json/json_value.cpp json/json_writer.cpp
304+ json_server.cc
305+ json/json_reader.cpp
306+ json/json_value.cpp
307+ json/json_writer.cpp
308 build_conditional="x${ac_cv_libevent}" = "xyes" -a "x${ac_cv_libcurl}" = "xyes"
309 ldflags=${LTLIBEVENT}
310-