Skip to content

Commit 33bee17

Browse files
slachiewiczclaude
andcommitted
THRIFT-4144: Listen before forking in the c_glib socket tests
Client: c_glib The tests bound fixed ports 51198 and 51199, inside the Linux ephemeral range, in a forked child while the parent slept a second. Any socket already holding the port made the child's unchecked listen fail and the parent's connect be refused. The parent now listens on a port the kernel picks before forking, and the child inherits the socket; do not bring back the fixed ports or the sleeps. Without the sleep, the plain server in testtransportsslsocket could reset the connection before the client wrote its handshake, killing the client with SIGPIPE. That server now reads the first byte before closing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent e69f8c0 commit 33bee17

14 files changed

Lines changed: 389 additions & 326 deletions

‎lib/c_glib/test/Makefile.am‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,5 +492,6 @@ distdir:
492492
EXTRA_DIST = \
493493
CMakeLists.txt \
494494
ContainerTest.thrift \
495-
RecursionLimitTest.thrift
495+
RecursionLimitTest.thrift \
496+
testserversocket.h
496497

‎lib/c_glib/test/testbinaryprotocol.c‎

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@
4646
#define TEST_I64 G_GINT64_CONSTANT (123456789012345)
4747
#define TEST_DOUBLE 1234567890.123
4848
#define TEST_STRING "this is a test string 1234567890!@#$%^&*()"
49-
#define TEST_PORT 51199
5049

5150
static int transport_read_count = 0;
5251
static int transport_read_error = 0;
@@ -85,10 +84,11 @@ my_thrift_transport_write (ThriftTransport *transport, const gpointer buf,
8584
#include "../src/thrift/c_glib/protocol/thrift_binary_protocol.c"
8685
#undef thrift_transport_read_all
8786
#undef thrift_transport_write
87+
#include "testserversocket.h"
8888

89-
static void thrift_server_primitives (const int port);
90-
static void thrift_server_complex_types (const int port);
91-
static void thrift_server_many_frames (const int port);
89+
static void thrift_server_primitives (ThriftServerSocket *tsocket);
90+
static void thrift_server_complex_types (ThriftServerSocket *tsocket);
91+
static void thrift_server_many_frames (ThriftServerSocket *tsocket);
9292

9393
static void
9494
test_create_and_destroy(void)
@@ -136,20 +136,23 @@ test_read_and_write_primitives(void)
136136
ThriftProtocol *protocol = NULL;
137137
gpointer binary = (gpointer *) TEST_STRING;
138138
guint32 len = strlen (TEST_STRING);
139-
int port = TEST_PORT;
139+
ThriftServerSocket *server = NULL;
140+
guint port = 0;
141+
142+
server = server_socket_new_on_free_port (NULL, &port);
140143

141144
/* fork a server from the client */
142145
pid = fork ();
143146
g_assert (pid >= 0);
144147

145148
if (pid == 0)
146149
{
147-
/* child listens */
148-
thrift_server_primitives (port);
150+
/* child accepts */
151+
thrift_server_primitives (server);
149152
exit (0);
150153
} else {
151-
/* parent. wait a bit for the socket to be created. */
152-
sleep (1);
154+
/* parent connects; the child owns the listening socket now */
155+
g_object_unref (server);
153156

154157
/* create a ThriftSocket */
155158
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
@@ -219,20 +222,23 @@ test_read_and_write_complex_types (void)
219222
ThriftTransport *transport = NULL;
220223
ThriftBinaryProtocol *tb = NULL;
221224
ThriftProtocol *protocol = NULL;
222-
int port = TEST_PORT;
225+
ThriftServerSocket *server = NULL;
226+
guint port = 0;
227+
228+
server = server_socket_new_on_free_port (NULL, &port);
223229

224230
/* fork a server from the client */
225231
pid = fork ();
226232
g_assert (pid >= 0);
227233

228234
if (pid == 0)
229235
{
230-
/* child listens */
231-
thrift_server_complex_types (port);
236+
/* child accepts */
237+
thrift_server_complex_types (server);
232238
exit (0);
233239
} else {
234-
/* parent. wait a bit for the socket to be created. */
235-
sleep (1);
240+
/* parent connects; the child owns the listening socket now */
241+
g_object_unref (server);
236242

237243
/* create a ThriftSocket */
238244
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
@@ -408,20 +414,23 @@ test_read_and_write_many_frames (void)
408414
ThriftProtocol *protocol = NULL;
409415
gpointer binary = (gpointer *) TEST_STRING;
410416
const guint32 len = strlen (TEST_STRING);
411-
int port = TEST_PORT;
417+
ThriftServerSocket *server = NULL;
418+
guint port = 0;
419+
420+
server = server_socket_new_on_free_port (NULL, &port);
412421

413422
/* fork a server from the client */
414423
pid = fork ();
415424
g_assert (pid >= 0);
416425

417426
if (pid == 0)
418427
{
419-
/* child listens */
420-
thrift_server_many_frames (port);
428+
/* child accepts */
429+
thrift_server_many_frames (server);
421430
exit (0);
422431
} else {
423-
/* parent. wait a bit for the socket to be created. */
424-
sleep (1);
432+
/* parent connects; the child owns the listening socket now */
433+
g_object_unref (server);
425434

426435
/* create a ThriftSocket */
427436
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
@@ -485,7 +494,7 @@ test_read_and_write_many_frames (void)
485494

486495

487496
static void
488-
thrift_server_primitives (const int port)
497+
thrift_server_primitives (ThriftServerSocket *tsocket)
489498
{
490499
ThriftServerTransport *transport = NULL;
491500
ThriftTransport *client = NULL;
@@ -503,10 +512,7 @@ thrift_server_primitives (const int port)
503512
guint32 len = 0;
504513
void *comparator = (void *) TEST_STRING;
505514

506-
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
507-
"port", port, NULL);
508515
transport = THRIFT_SERVER_TRANSPORT (tsocket);
509-
thrift_server_transport_listen (transport, NULL);
510516
client = thrift_server_transport_accept (transport, NULL);
511517
g_assert (client != NULL);
512518

@@ -585,7 +591,7 @@ thrift_server_primitives (const int port)
585591
}
586592

587593
static void
588-
thrift_server_complex_types (const int port)
594+
thrift_server_complex_types (ThriftServerSocket *tsocket)
589595
{
590596
ThriftServerTransport *transport = NULL;
591597
ThriftTransport *client = NULL;
@@ -602,10 +608,7 @@ thrift_server_complex_types (const int port)
602608
gint32 seqid = 0;
603609
gint32 version = 0;
604610

605-
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
606-
"port", port, NULL);
607611
transport = THRIFT_SERVER_TRANSPORT (tsocket);
608-
thrift_server_transport_listen (transport, NULL);
609612
client = thrift_server_transport_accept (transport, NULL);
610613
g_assert (client != NULL);
611614

@@ -773,13 +776,12 @@ thrift_server_complex_types (const int port)
773776
}
774777

775778
static void
776-
thrift_server_many_frames (const int port)
779+
thrift_server_many_frames (ThriftServerSocket *tsocket)
777780
{
778781
ThriftServerTransport *transport = NULL;
779782
ThriftTransport *client = NULL;
780783
ThriftBinaryProtocol *tbp = NULL;
781784
ThriftProtocol *protocol = NULL;
782-
ThriftServerSocket *tsocket = NULL;
783785
gboolean value_boolean = FALSE;
784786
gint8 value_byte = 0;
785787
gint16 value_16 = 0;
@@ -792,9 +794,7 @@ thrift_server_many_frames (const int port)
792794
guint32 len = 0;
793795
void *comparator = (void *) TEST_STRING;
794796

795-
tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, "port", port, NULL);
796797
transport = THRIFT_SERVER_TRANSPORT (tsocket);
797-
thrift_server_transport_listen (transport, NULL);
798798

799799
/* wrap the client in a framed transport */
800800
client = g_object_new (THRIFT_TYPE_FRAMED_TRANSPORT, "transport",

‎lib/c_glib/test/testbufferedtransport.c‎

Lines changed: 32 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030
#define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }
3131

3232
#include "../src/thrift/c_glib/transport/thrift_buffered_transport.c"
33+
#include "testserversocket.h"
3334

34-
static void thrift_server (const int port);
35-
static void thrift_socket_server_open (const int port, int times);
35+
static void thrift_server (ThriftServerSocket *tsocket);
36+
static void thrift_socket_server_open (ThriftServerSocket *tsocket, int times);
3637

3738
/* test object creation and destruction */
3839
static void
@@ -58,20 +59,23 @@ test_open_and_close(void)
5859
ThriftTransport *transport = NULL;
5960
GError *err = NULL;
6061
pid_t pid;
61-
int port = 51199;
62+
ThriftServerSocket *server = NULL;
63+
guint port = 0;
6264
int status;
6365

66+
server = server_socket_new_on_free_port (NULL, &port);
67+
6468
pid = fork ();
6569
g_assert ( pid >= 0 );
6670

6771
if ( pid == 0 )
6872
{
69-
/* child listens */
70-
thrift_socket_server_open (port,1);
73+
/* child accepts */
74+
thrift_socket_server_open (server,1);
7175
exit (0);
7276
} else {
73-
/* parent connects, wait a bit for the socket to be created */
74-
sleep (1);
77+
/* parent connects; the child owns the listening socket now */
78+
g_object_unref (server);
7579
/* create a ThriftSocket */
7680
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
7781
"port", port, NULL);
@@ -112,20 +116,23 @@ test_read_and_write(void)
112116
pid_t pid;
113117
ThriftSocket *tsocket = NULL;
114118
ThriftTransport *transport = NULL;
115-
int port = 51199;
119+
ThriftServerSocket *server = NULL;
120+
guint port = 0;
116121
guchar buf[10] = TEST_DATA; /* a buffer */
117122

123+
server = server_socket_new_on_free_port (NULL, &port);
124+
118125
pid = fork ();
119126
g_assert ( pid >= 0 );
120127

121128
if ( pid == 0 )
122129
{
123-
/* child listens */
124-
thrift_server (port);
130+
/* child accepts */
131+
thrift_server (server);
125132
exit (0);
126133
} else {
127-
/* parent connects, wait a bit for the socket to be created */
128-
sleep (1);
134+
/* parent connects; the child owns the listening socket now */
135+
g_object_unref (server);
129136

130137
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
131138
"port", port, NULL);
@@ -174,16 +181,12 @@ test_read_and_write(void)
174181

175182

176183
static void
177-
thrift_socket_server_open (const int port, int times)
184+
thrift_socket_server_open (ThriftServerSocket *tsocket, int times)
178185
{
179-
ThriftServerTransport *transport = NULL;
186+
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (tsocket);
180187
ThriftTransport *client = NULL;
181188
int i;
182-
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
183-
"port", port, NULL);
184189

185-
transport = THRIFT_SERVER_TRANSPORT (tsocket);
186-
thrift_server_transport_listen (transport, NULL);
187190
for(i=0;i<times;i++){
188191
client = thrift_server_transport_accept (transport, NULL);
189192
g_assert (client != NULL);
@@ -194,20 +197,14 @@ thrift_socket_server_open (const int port, int times)
194197
}
195198

196199
static void
197-
thrift_server (const int port)
200+
thrift_server (ThriftServerSocket *tsocket)
198201
{
199202
int bytes = 0;
200-
ThriftServerTransport *transport = NULL;
203+
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (tsocket);
201204
ThriftTransport *client = NULL;
202205
guchar buf[10]; /* a buffer */
203206
guchar match[10] = TEST_DATA;
204207

205-
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
206-
"port", port, NULL);
207-
208-
transport = THRIFT_SERVER_TRANSPORT (tsocket);
209-
thrift_server_transport_listen (transport, NULL);
210-
211208
/* wrap the client in a BufferedTransport */
212209
client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport",
213210
thrift_server_transport_accept (transport, NULL),
@@ -239,27 +236,24 @@ test_write_fail(void)
239236
pid_t pid;
240237
ThriftSocket *tsocket = NULL;
241238
ThriftTransport *transport = NULL;
242-
int port = 51198;
239+
ThriftServerSocket *server = NULL;
240+
guint port = 0;
243241
guchar buf[10] = TEST_DATA; /* a buffer */
244242

245243
/* SIGPIPE when send to disconnected socket */
246244
signal(SIGPIPE, SIG_IGN);
247245

246+
server = server_socket_new_on_free_port (NULL, &port);
247+
248248
pid = fork ();
249249
g_assert ( pid >= 0 );
250250

251251
if ( pid == 0 )
252252
{
253-
/* child listens */
254-
ThriftServerTransport *transport = NULL;
253+
/* child accepts */
254+
ThriftServerTransport *transport = THRIFT_SERVER_TRANSPORT (server);
255255
ThriftTransport *client = NULL;
256256

257-
ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET,
258-
"port", port, NULL);
259-
260-
transport = THRIFT_SERVER_TRANSPORT (tsocket);
261-
thrift_server_transport_listen (transport, NULL);
262-
263257
/* wrap the client in a BufferedTransport */
264258
client = g_object_new (THRIFT_TYPE_BUFFERED_TRANSPORT, "transport",
265259
thrift_server_transport_accept (transport, NULL),
@@ -269,11 +263,11 @@ test_write_fail(void)
269263
/* just close socket */
270264
thrift_buffered_transport_close (client, NULL);
271265
g_object_unref (client);
272-
g_object_unref (tsocket);
266+
g_object_unref (server);
273267
exit (0);
274268
} else {
275-
/* parent connects, wait a bit for the socket to be created */
276-
sleep (1);
269+
/* parent connects; the child owns the listening socket now */
270+
g_object_unref (server);
277271

278272
tsocket = g_object_new (THRIFT_TYPE_SOCKET, "hostname", "localhost",
279273
"port", port, NULL);

0 commit comments

Comments
 (0)