Merge lp:~schuster/mysql-proxy/remove_unix_socket into lp:mysql-proxy
- remove_unix_socket
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1081 |
Proposed branch: | lp:~schuster/mysql-proxy/remove_unix_socket |
Merge into: | lp:mysql-proxy |
Diff against target: |
231 lines (+130/-5) 4 files modified
src/network-address.c (+28/-1) src/network-address.h (+1/-1) src/network-socket.c (+1/-0) tests/unit/t_network_socket.c (+100/-3) |
To merge this branch: | bzr merge lp:~schuster/mysql-proxy/remove_unix_socket |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jan Kneschke (community) | Approve | ||
Review via email: mp+23652@code.launchpad.net |
Commit message
Description of the change
Jan Kneschke (jan-kneschke) wrote : | # |
Michael Schuster (schuster) wrote : | # |
On 04/19/10 09:39, Jan Kneschke wrote:
> Am 19.04.2010 um 08:48 schrieb Michael Schuster:
>
>> Michael Schuster has proposed merging lp:~schuster/mysql-proxy/remove_unix_socket into lp:mysql-proxy.
>>
>> Requested reviews:
>> MySQL Proxy Developers (mysql-
>>
>> --
>> https:/
>> Your team MySQL Proxy Developers is subscribed to branch lp:mysql-proxy.
>> === modified file 'src/network-
>> --- src/network-
>> +++ src/network-
>> @@ -45,6 +45,8 @@
>> #include <string.h>
>> #include <errno.h>
>> #include <fcntl.h>
>> +#include <glib.h>
>> +#include <glib/gstdio.h>
>>
>> #include "network-address.h"
>> #include "glib-ext.h"
>> @@ -63,10 +65,33 @@
>> }
>>
>> void network_
>> +
>> if (!addr) return;
>>
>> +#ifndef WIN32
>> + /*
>> + * if the name we're freeing starts with a '/', we're
>> + * looking at a unix socket which needs to be removed
>> + */
>> + if (addr->fail_errno == 0 && addr->name != NULL &&
>> + addr->name->str != NULL) {
>> + gchar *name;
>> + int ret;
>> +
>> + name = addr->name->str;
>> + if (name[0] == '/' && g_access(name, 0) == 0) {
>> + ret = g_remove(name);
>
> Only try to remove it if we can to hide the error-msg (aka noise) for it ?
sorry, don't understand the question :-(
>> +
>> + if (ret == 0)
>> + g_debug("%s removing socket %s successful",
>> + G_STRLOC, name);
>> + else
>> + g_debug("%s removing socket %s failed: %s (%d)",
>> + G_STRLOC, name, strerror(errno));
>
> ... in that case the g_debug() is perhaps better a g_critical() ?
ok.
Michael
- 1049. By Michael Schuster
-
change warning level for failure to remove socket
Jan Kneschke (jan-kneschke) wrote : | # |
Am 19.04.2010 um 10:45 schrieb Michael Schuster:
> On 04/19/10 09:39, Jan Kneschke wrote:
>> Am 19.04.2010 um 08:48 schrieb Michael Schuster:
>>
>>> Michael Schuster has proposed merging lp:~schuster/mysql-proxy/remove_unix_socket into lp:mysql-proxy.
>>>
>>> Requested reviews:
>>> MySQL Proxy Developers (mysql-
>>>
>>> --
>>> https:/
>>> Your team MySQL Proxy Developers is subscribed to branch lp:mysql-proxy.
>>> === modified file 'src/network-
>>> --- src/network-
>>> +++ src/network-
>>> @@ -45,6 +45,8 @@
>>> #include <string.h>
>>> #include <errno.h>
>>> #include <fcntl.h>
>>> +#include <glib.h>
>>> +#include <glib/gstdio.h>
>>>
>>> #include "network-address.h"
>>> #include "glib-ext.h"
>>> @@ -63,10 +65,33 @@
>>> }
>>>
>>> void network_
>>> +
>>> if (!addr) return;
>>>
>>> +#ifndef WIN32
>>> + /*
>>> + * if the name we're freeing starts with a '/', we're
>>> + * looking at a unix socket which needs to be removed
>>> + */
>>> + if (addr->fail_errno == 0 && addr->name != NULL &&
>>> + addr->name->str != NULL) {
>>> + gchar *name;
>>> + int ret;
>>> +
>>> + name = addr->name->str;
>>> + if (name[0] == '/' && g_access(name, 0) == 0) {
>>> + ret = g_remove(name);
>>
>> Only try to remove it if we can to hide the error-msg (aka noise) for it ?
>
> sorry, don't understand the question :-(
I tried to figure out the reason for the g_access() and assumed it is to check if the g_remove() could succeed without a permission problem.
Problem with access() is that it creates a race-condition before the the permission check and the g_remove(). Instead just unlink() it and check for the 'errno != EPERM' to see if we can't delete the socket as we drop the privileges.
>>> +
>>> + if (ret == 0)
>>> + g_debug("%s removing socket %s successful",
>>> + G_STRLOC, name);
>>> + else
>>> + g_debug("%s removing socket %s failed: %s (%d)",
>>> + G_STRLOC, name, strerror(errno));
>>
>> ... in that case the g_debug() is perhaps better a g_critical() ?
>
> ok.
The whole patch does unlink() any file that is set as address. In the case of a network_
Instead of ->fail_errno use a gboolean to track if you want to unlink the socket file on free and only set it to true in the case of a successful network_
> Michael
> --
> https:/
> Your team MySQL Proxy Developers is subscribed to branch lp:mysql-proxy.
Jan Kneschke (jan-kneschke) wrote : | # |
A test-case to verify that we don't unlink() socket-files we havn't bound
1 | === modified file 'tests/unit/t_network_address.c' |
2 | --- tests/unit/t_network_address.c revid:michael.schuster@oracle.com-20100423113047-u7cepgr9b32hgxag |
3 | +++ tests/unit/t_network_address.c 2010-04-28 07:07:30 +0000 |
4 | @@ -21,9 +21,14 @@ |
5 | #include <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | +#include <fcntl.h> |
9 | |
10 | #include <glib.h> |
11 | |
12 | +#ifndef _WIN32 |
13 | +#include <unistd.h> |
14 | +#endif |
15 | + |
16 | #include "network-socket.h" |
17 | |
18 | #if GLIB_CHECK_VERSION(2, 16, 0) |
19 | @@ -80,6 +85,38 @@ |
20 | network_address_free(addr); |
21 | } |
22 | |
23 | +/** |
24 | + * test if we decode the port number correctly |
25 | + */ |
26 | +void t_network_address_free_unix_socket() { |
27 | + network_address *addr; |
28 | + int fd; |
29 | + |
30 | +#define TESTFILE "/tmp/mysql-proxy-t_network_address_free_unix_socket.sock" |
31 | + unlink(TESTFILE); /* remove the file if a previous test-run failed */ |
32 | + |
33 | + /* create the test-file */ |
34 | + fd = open(TESTFILE, O_RDONLY | O_CREAT | O_EXCL, 0600); |
35 | + if (fd != -1) close(fd); |
36 | + |
37 | + g_assert_cmpint(fd, >, 0); /* creating the file should have succeeded */ |
38 | + |
39 | + addr = network_address_new(); |
40 | + network_address_set_address(addr, TESTFILE); |
41 | + |
42 | + network_address_free(addr); /* the free shouldn't remove the file as we didn't call bind() on it */ |
43 | + |
44 | + /* file should still be there */ |
45 | + fd = open(TESTFILE, O_RDONLY); |
46 | + if (fd != -1) close(fd); |
47 | + |
48 | + g_assert_cmpint(fd, >, 0); |
49 | + |
50 | + unlink(TESTFILE); /* cleanup */ |
51 | +#undef TESTFILE |
52 | +} |
53 | + |
54 | + |
55 | |
56 | int main(int argc, char **argv) { |
57 | g_test_init(&argc, &argv, NULL); |
58 | @@ -88,6 +125,7 @@ |
59 | g_test_add_func("/core/network_address_new", t_network_address_new); |
60 | g_test_add_func("/core/network_address_set", t_network_address_set); |
61 | g_test_add_func("/core/network_address_resolve", t_network_address_resolve); |
62 | + g_test_add_func("/core/network_address_free_unix_socket", t_network_address_free_unix_socket); |
63 | |
64 | return g_test_run(); |
65 | } |
- 1050. By Michael Schuster
-
remove unix socket at shutdown: remove race window, make logic for "remove the once we created only" better
- 1051. By Michael Schuster
-
add check for local socket removal to "is local" testcase
- 1052. By Michael Schuster
-
make sure socket is removed if assertion fails: add sig handler for SIGARBT
Jan Kneschke (jan-kneschke) wrote : | # |
* remove the commented lines:
/* printf("debug: socket name is %s (addr: %p)\n", pp->sockname, pp); */
/* g_test_
* stay with the existing coding style (no line-break after function declarations)
* The signal-handler for SIGABRT is installed for _all_ tests of this test-suite. Instead it should be added in the setup and turned back into SIG_DFL in teardown.
* void t_network_
Jan Kneschke (jan-kneschke) wrote : | # |
g_debug("%s removing socket %s successful", ... is missing a colon after the first %s
Jan Kneschke (jan-kneschke) : | # |
Michael Schuster (schuster) wrote : | # |
Jan,
thx for review, comments in-line.
On 04.05.10 13:50, Jan Kneschke wrote:
> * remove the commented lines:
>
> /* printf("debug: socket name is %s (addr: %p)\n", pp->sockname, pp); */
> /* g_test_
done
> * stay with the existing coding style (no line-break after function declarations)
ack, done.
> * The signal-handler for SIGABRT is installed for _all_ tests of this test-suite. Instead it should be added in the setup and turned back into SIG_DFL in teardown.
done
> * void t_network_
ack
> g_debug("%s removing socket %s successful", ... is missing a colon after the first %s
this is now gone.
Michael
--
Michael Schuster http://
Recursion, n.: see 'Recursion'
- 1053. By Michael Schuster
-
fix diversion
Jan Kneschke (jan-kneschke) wrote : | # |
approved. will merge it to trunk
Jan Kneschke (jan-kneschke) wrote : | # |
65 === modified file 'src/network-
66 --- src/network-
67 +++ src/network-
...
In static network_
76 @@ -660,6 +661,7 @@
77 }
78 }
79
80 + con->dst-
81 return NETWORK_
82 }
which would mean:
"unlink socket after successful write" which isn't what we want. Seems to a broken merge. The rest looks good.
- 1054. By Michael Schuster
-
mismerge fixed
Jan Kneschke (jan-kneschke) : | # |
Preview Diff
1 | === modified file 'src/network-address.c' |
2 | --- src/network-address.c 2010-04-07 12:44:32 +0000 |
3 | +++ src/network-address.c 2010-05-10 12:15:45 +0000 |
4 | @@ -45,6 +45,8 @@ |
5 | #include <string.h> |
6 | #include <errno.h> |
7 | #include <fcntl.h> |
8 | +#include <glib.h> |
9 | +#include <glib/gstdio.h> |
10 | |
11 | #include "network-address.h" |
12 | #include "glib-ext.h" |
13 | @@ -63,10 +65,35 @@ |
14 | } |
15 | |
16 | void network_address_free(network_address *addr) { |
17 | + |
18 | if (!addr) return; |
19 | |
20 | +#ifndef WIN32 |
21 | + /* |
22 | + * if the name we're freeing starts with a '/', we're |
23 | + * looking at a unix socket which needs to be removed |
24 | + */ |
25 | + if (addr->can_unlink_socket == TRUE && addr->name != NULL && |
26 | + addr->name->str != NULL) { |
27 | + gchar *name; |
28 | + int ret; |
29 | + |
30 | + name = addr->name->str; |
31 | + if (name[0] == '/') { |
32 | + ret = g_remove(name); |
33 | + if (ret == 0) { |
34 | + g_debug("%s: removing socket %s successful", |
35 | + G_STRLOC, name); |
36 | + } else { |
37 | + if (errno != EPERM && errno != EACCES) |
38 | + g_critical("%s: removing socket %s failed: %s (%d)", |
39 | + G_STRLOC, name, strerror(errno)); |
40 | + } |
41 | + } |
42 | + } |
43 | +#endif /* WIN32 */ |
44 | + |
45 | g_string_free(addr->name, TRUE); |
46 | - |
47 | g_free(addr); |
48 | } |
49 | |
50 | |
51 | === modified file 'src/network-address.h' |
52 | --- src/network-address.h 2010-04-06 14:26:51 +0000 |
53 | +++ src/network-address.h 2010-05-10 12:15:45 +0000 |
54 | @@ -63,8 +63,8 @@ |
55 | } addr; |
56 | |
57 | GString *name; |
58 | - |
59 | network_socklen_t len; |
60 | + gboolean can_unlink_socket; /* set TRUE *only* after successful bind */ |
61 | } network_address; |
62 | |
63 | NETWORK_API network_address *network_address_new(void); |
64 | |
65 | === modified file 'src/network-socket.c' |
66 | --- src/network-socket.c 2010-05-03 14:26:32 +0000 |
67 | +++ src/network-socket.c 2010-05-10 12:15:45 +0000 |
68 | @@ -431,6 +431,7 @@ |
69 | } |
70 | } |
71 | |
72 | + con->dst->can_unlink_socket = TRUE; |
73 | return NETWORK_SOCKET_SUCCESS; |
74 | } |
75 | |
76 | |
77 | === modified file 'tests/unit/t_network_socket.c' |
78 | --- tests/unit/t_network_socket.c 2010-04-07 12:44:32 +0000 |
79 | +++ tests/unit/t_network_socket.c 2010-05-10 12:15:45 +0000 |
80 | @@ -23,6 +23,12 @@ |
81 | #include <string.h> |
82 | #include <errno.h> |
83 | |
84 | +#ifndef WIN32 |
85 | +#include <unistd.h> |
86 | +#include <stdlib.h> |
87 | +#include <fcntl.h> |
88 | +#endif /* WIN32 */ |
89 | + |
90 | #include <glib.h> |
91 | #include <glib/gstdio.h> /* for g_unlink */ |
92 | |
93 | @@ -31,6 +37,17 @@ |
94 | #if GLIB_CHECK_VERSION(2, 16, 0) |
95 | #define C(x) x, sizeof(x) - 1 |
96 | |
97 | +#ifndef WIN32 |
98 | +#define LOCAL_SOCK "/tmp/mysql-proxy-test.socket" |
99 | + |
100 | +typedef struct { |
101 | + char sockname[sizeof(LOCAL_SOCK) + 10]; |
102 | +} local_unix_t; |
103 | + |
104 | +static local_unix_t *pp = NULL; |
105 | +static local_unix_t local_test_arg; |
106 | +#endif /* WIN32 */ |
107 | + |
108 | void test_network_socket_new() { |
109 | network_socket *sock; |
110 | |
111 | @@ -295,6 +312,8 @@ |
112 | network_socket_free(server); |
113 | } |
114 | |
115 | +#ifndef WIN32 |
116 | + |
117 | /** |
118 | * test if _is_local() works on unix-domain sockets |
119 | * |
120 | @@ -314,6 +333,7 @@ |
121 | c_sock = network_socket_new(); |
122 | network_address_set_address(c_sock->dst, "/tmp/mysql-proxy-test.socket"); |
123 | |
124 | + |
125 | /* hack together a network_socket_accept() which we don't have in this tree yet */ |
126 | g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(s_sock)); |
127 | |
128 | @@ -331,6 +351,76 @@ |
129 | g_unlink("/tmp/mysql-proxy-test.socket"); |
130 | } |
131 | |
132 | +void t_network_localsocket_setup(local_unix_t *p) { |
133 | + g_assert(p != NULL); |
134 | + snprintf(p->sockname, sizeof(p->sockname), LOCAL_SOCK ".%d", (int)getpid()); |
135 | + pp = p; |
136 | +} |
137 | + |
138 | +void t_network_localsocket_teardown(local_unix_t *p) { |
139 | + g_assert(p != NULL); |
140 | + if (p->sockname[0] != '\0') { |
141 | + (void) g_unlink(p->sockname); |
142 | + p->sockname[0] = '\0'; |
143 | + } |
144 | + pp = NULL; |
145 | +} |
146 | + |
147 | +void exitfunc(int sig) { |
148 | + if (pp != NULL && pp->sockname[0] != '\0') |
149 | + (void) g_unlink(pp->sockname); |
150 | + |
151 | + abort(); |
152 | +} |
153 | + |
154 | +/** |
155 | + * test if local sockets are removed at shutdown |
156 | + * this is an extension of _is_local_unix(), therefore looks much like it; |
157 | + * just in case, we leave all tests from that function in as well. |
158 | + */ |
159 | +void t_network_socket_rem_local_unix(local_unix_t *p) { |
160 | + network_socket *s_sock; /* the server side socket, listening for requests */ |
161 | + network_socket *c_sock; /* the client side socket, that connects */ |
162 | + network_socket *a_sock; /* the server side, accepted socket */ |
163 | + |
164 | + /* |
165 | + * if an assertion fails, we receive the ABORT signal. We need to |
166 | + * close the unix socket in that case too. The regular teardown function |
167 | + * is not called in this case, so we install our own handler. |
168 | + */ |
169 | + signal(SIGABRT, exitfunc); |
170 | + g_test_bug("42220"); |
171 | + g_log_set_always_fatal(G_LOG_FATAL_MASK); /* gtest modifies the fatal-mask */ |
172 | + |
173 | + s_sock = network_socket_new(); |
174 | + network_address_set_address(s_sock->dst, p->sockname); |
175 | + |
176 | + c_sock = network_socket_new(); |
177 | + network_address_set_address(c_sock->dst, p->sockname); |
178 | + |
179 | + g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_bind(s_sock)); |
180 | + |
181 | + g_assert_cmpint(g_access(p->sockname, 0), ==, 0); |
182 | + |
183 | + g_assert_cmpint(NETWORK_SOCKET_SUCCESS, ==, network_socket_connect(c_sock)); |
184 | + |
185 | + a_sock = network_socket_accept(s_sock); |
186 | + g_assert(a_sock); |
187 | + |
188 | + g_assert_cmpint(TRUE, ==, network_address_is_local(s_sock->dst, a_sock->dst)); |
189 | + |
190 | + network_socket_free(a_sock); |
191 | + g_assert_cmpint(g_access(p->sockname, 0), ==, 0); |
192 | + network_socket_free(c_sock); |
193 | + g_assert_cmpint(g_access(p->sockname, 0), ==, 0); |
194 | + network_socket_free(s_sock); |
195 | + g_assert_cmpint(g_access(p->sockname, 0), ==, -1); |
196 | + |
197 | + /* re-establish default signal disposition */ |
198 | + signal(SIGABRT, SIG_DFL); |
199 | +} |
200 | + |
201 | +#endif /* WIN32 */ |
202 | |
203 | int main(int argc, char **argv) { |
204 | g_test_init(&argc, &argv, NULL); |
205 | @@ -342,7 +432,14 @@ |
206 | g_test_add_func("/core/network_queue_append", test_network_queue_append); |
207 | g_test_add_func("/core/network_queue_peek_string", test_network_queue_peek_string); |
208 | g_test_add_func("/core/network_queue_pop_string", test_network_queue_pop_string); |
209 | - g_test_add_func("/core/network_socket_is_local_unix", t_network_socket_is_local_unix); |
210 | +#ifndef WIN32 |
211 | + g_test_add_func("/core/network_socket_is_local_unix",t_network_socket_is_local_unix); |
212 | + |
213 | + g_test_add("/core/network_socket_rem_local_unix", local_unix_t, |
214 | + &local_test_arg, |
215 | + t_network_localsocket_setup, t_network_socket_rem_local_unix, |
216 | + t_network_localsocket_teardown); |
217 | +#endif /* WIN32 */ |
218 | #if 0 |
219 | /** |
220 | * disabled for now until we fixed the _to_read() on HP/UX and AIX (and MacOS X) |
221 | @@ -354,8 +451,8 @@ |
222 | |
223 | return g_test_run(); |
224 | } |
225 | -#else |
226 | +#else /* GLIB_CHECK_VERSION */ |
227 | int main() { |
228 | return 77; |
229 | } |
230 | -#endif |
231 | +#endif /* GLIB_CHECK_VERSION */ |
Am 19.04.2010 um 08:48 schrieb Michael Schuster:
> Michael Schuster has proposed merging lp:~schuster/mysql-proxy/remove_unix_socket into lp:mysql-proxy. proxy-developer s) /code.launchpad .net/~schuster/ mysql-proxy/ remove_ unix_socket/ +merge/ 23652 address. c' address. c 2010-04-07 12:44:32 +0000 address. c 2010-04-19 06:48:19 +0000 address_ free(network_ address *addr) {
>
> Requested reviews:
> MySQL Proxy Developers (mysql-
>
> --
> https:/
> Your team MySQL Proxy Developers is subscribed to branch lp:mysql-proxy.
> === modified file 'src/network-
> --- src/network-
> +++ src/network-
> @@ -45,6 +45,8 @@
> #include <string.h>
> #include <errno.h>
> #include <fcntl.h>
> +#include <glib.h>
> +#include <glib/gstdio.h>
>
> #include "network-address.h"
> #include "glib-ext.h"
> @@ -63,10 +65,33 @@
> }
>
> void network_
> +
> if (!addr) return;
>
> +#ifndef WIN32
> + /*
> + * if the name we're freeing starts with a '/', we're
> + * looking at a unix socket which needs to be removed
> + */
> + if (addr->fail_errno == 0 && addr->name != NULL &&
> + addr->name->str != NULL) {
> + gchar *name;
> + int ret;
> +
> + name = addr->name->str;
> + if (name[0] == '/' && g_access(name, 0) == 0) {
> + ret = g_remove(name);
Only try to remove it if we can to hide the error-msg (aka noise) for it ?
> +
> + if (ret == 0)
> + g_debug("%s removing socket %s successful",
> + G_STRLOC, name);
> + else
> + g_debug("%s removing socket %s failed: %s (%d)",
> + G_STRLOC, name, strerror(errno));
... in that case the g_debug() is perhaps better a g_critical() ?
> + } free(addr- >name, TRUE); address. h' address. h 2010-04-06 14:26:51 +0000 address. h 2010-04-19 06:48:19 +0000 address_ new(void) ; socket. c' socket. c 2010-04-06 14:26:51 +0000 socket. c 2010-04-19 06:48:19 +0000 >name-> str, >fail_errno = errno; /* if a unix socket, this tells us "don't remove" */ SOCKET_ ERROR;
> + }
> +#endif /* WIN32 */
> +
> g_string_
> -
> g_free(addr);
> }
>
>
> === modified file 'src/network-
> --- src/network-
> +++ src/network-
> @@ -63,8 +63,8 @@
> } addr;
>
> GString *name;
> -
> network_socklen_t len;
> + int fail_errno; /* != 0: don't remove ... I guess */
> } network_address;
>
> NETWORK_API network_address *network_
>
> === modified file 'src/network-
> --- src/network-
> +++ src/network-
> @@ -397,6 +397,7 @@
> G_STRLOC,
> con->dst-
> g_strerror(errno), errno);
> + con->dst-
> return NETWORK_
> }
>
>