Commit 612d81a8 authored by Jim Klimov's avatar Jim Klimov Committed by GitHub

Merge pull request #2659 from bluca/fix_getrandom

Problems: test_security_curve occasionally hangs or fails due to ECONNABORTED
parents 20bbd016 5f6ff69f
...@@ -148,13 +148,42 @@ enum zap_protocol_t ...@@ -148,13 +148,42 @@ enum zap_protocol_t
zap_too_many_parts zap_too_many_parts
}; };
static void zap_handler_generic (void *handler, zap_protocol_t zap_protocol) static void zap_handler_generic (void *ctx, zap_protocol_t zap_protocol)
{ {
void *control = zmq_socket (ctx, ZMQ_REQ);
assert (control);
int rc = zmq_connect (control, "inproc://handler-control");
assert (rc == 0);
void *handler = zmq_socket (ctx, ZMQ_REP);
assert (handler);
rc = zmq_bind (handler, "inproc://zeromq.zap.01");
assert (rc == 0);
// Signal main thread that we are ready
rc = s_send (control, "GO");
assert (rc == 2);
zmq_pollitem_t items [] = {
{ control, 0, ZMQ_POLLIN, 0 },
{ handler, 0, ZMQ_POLLIN, 0 },
};
// Process ZAP requests forever // Process ZAP requests forever
while (true) { while (zmq_poll (items, 2, -1) >= 0) {
if (items [0].revents & ZMQ_POLLIN) {
char *buf = s_recv (control);
assert (buf);
assert (streq (buf, "STOP"));
free (buf);
break; // Terminating - main thread signal
}
if (!(items [1].revents & ZMQ_POLLIN))
continue;
char *version = s_recv (handler); char *version = s_recv (handler);
if (!version) if (!version)
break; // Terminating break; // Terminating - peer's socket closed
char *sequence = s_recv (handler); char *sequence = s_recv (handler);
char *domain = s_recv (handler); char *domain = s_recv (handler);
...@@ -206,37 +235,43 @@ static void zap_handler_generic (void *handler, zap_protocol_t zap_protocol) ...@@ -206,37 +235,43 @@ static void zap_handler_generic (void *handler, zap_protocol_t zap_protocol)
zmq_atomic_counter_inc (zap_requests_handled); zmq_atomic_counter_inc (zap_requests_handled);
} }
zmq_close (handler); rc = zmq_unbind (handler, "inproc://zeromq.zap.01");
assert (rc == 0);
close_zero_linger (handler);
rc = s_send (control, "STOPPED");
assert (rc == 7);
close_zero_linger (control);
} }
static void zap_handler (void *handler) static void zap_handler (void *ctx)
{ {
zap_handler_generic (handler, zap_ok); zap_handler_generic (ctx, zap_ok);
} }
static void zap_handler_wrong_version (void *handler) static void zap_handler_wrong_version (void *ctx)
{ {
zap_handler_generic (handler, zap_wrong_version); zap_handler_generic (ctx, zap_wrong_version);
} }
static void zap_handler_wrong_request_id (void *handler) static void zap_handler_wrong_request_id (void *ctx)
{ {
zap_handler_generic (handler, zap_wrong_request_id); zap_handler_generic (ctx, zap_wrong_request_id);
} }
static void zap_handler_wrong_status_invalid (void *handler) static void zap_handler_wrong_status_invalid (void *ctx)
{ {
zap_handler_generic (handler, zap_status_invalid); zap_handler_generic (ctx, zap_status_invalid);
} }
static void zap_handler_wrong_status_internal_error (void *handler) static void zap_handler_wrong_status_internal_error (void *ctx)
{ {
zap_handler_generic (handler, zap_status_internal_error); zap_handler_generic (ctx, zap_status_internal_error);
} }
static void zap_handler_too_many_parts (void *handler) static void zap_handler_too_many_parts (void *ctx)
{ {
zap_handler_generic (handler, zap_too_many_parts); zap_handler_generic (ctx, zap_too_many_parts);
} }
void *create_and_connect_curve_client (void *ctx, void *create_and_connect_curve_client (void *ctx,
...@@ -276,8 +311,8 @@ void expect_new_client_curve_bounce_fail (void *ctx, ...@@ -276,8 +311,8 @@ void expect_new_client_curve_bounce_fail (void *ctx,
// expects that one or more occurrences of the expected event are received // expects that one or more occurrences of the expected event are received
// via the specified socket monitor // via the specified socket monitor
// returns the number of occurrences of the expected event // returns the number of occurrences of the expected event
// interrupts, if a ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL/EPIPE/ECONNRESET // interrupts, if a ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL with EPIPE, ECONNRESET
// occurs; in this case, 0 is returned // or ECONNABORTED occurs; in this case, 0 is returned
// this should be investigated further, see // this should be investigated further, see
// https://github.com/zeromq/libzmq/issues/2644 // https://github.com/zeromq/libzmq/issues/2644
int expect_monitor_event_multiple (void *server_mon, int expect_monitor_event_multiple (void *server_mon,
...@@ -295,11 +330,12 @@ int expect_monitor_event_multiple (void *server_mon, ...@@ -295,11 +330,12 @@ int expect_monitor_event_multiple (void *server_mon,
!= -1) { != -1) {
timeout = 250; timeout = 250;
// ignore errors with EPIPE/ECONNRESET, which happen sporadically // ignore errors with EPIPE/ECONNRESET/ECONNABORTED, which can happen
// ECONNRESET can happen on very slow machines, when the engine writes // ECONNRESET can happen on very slow machines, when the engine writes
// to the peer and then tries to read the socket before the peer reads // to the peer and then tries to read the socket before the peer reads
// ECONNABORTED happens when a client aborts a connection via RST/timeout
if (event == ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL && if (event == ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL &&
(err == EPIPE || err == ECONNRESET)) { (err == EPIPE || err == ECONNRESET || err == ECONNABORTED)) {
fprintf (stderr, "Ignored event: %x (err = %i)\n", event, err); fprintf (stderr, "Ignored event: %x (err = %i)\n", event, err);
client_closed_connection = 1; client_closed_connection = 1;
break; break;
...@@ -360,13 +396,17 @@ void setup_context_and_server_side (void **ctx, ...@@ -360,13 +396,17 @@ void setup_context_and_server_side (void **ctx,
zap_requests_handled = zmq_atomic_counter_new (); zap_requests_handled = zmq_atomic_counter_new ();
assert (zap_requests_handled != NULL); assert (zap_requests_handled != NULL);
// We create and bind ZAP socket in main thread to avoid case
// where child thread does not start up fast enough.
*handler = zmq_socket (*ctx, ZMQ_REP); *handler = zmq_socket (*ctx, ZMQ_REP);
assert (*handler); assert (*handler);
int rc = zmq_bind (*handler, "inproc://zeromq.zap.01"); int rc = zmq_bind (*handler, "inproc://handler-control");
assert (rc == 0); assert (rc == 0);
*zap_thread = zmq_threadstart (zap_handler_, *handler);
*zap_thread = zmq_threadstart (zap_handler_, *ctx);
char *buf = s_recv (*handler);
assert (buf);
assert (streq (buf, "GO"));
free (buf);
// Server socket will accept connections // Server socket will accept connections
*server = zmq_socket (*ctx, ZMQ_DEALER); *server = zmq_socket (*ctx, ZMQ_DEALER);
...@@ -413,19 +453,30 @@ void setup_context_and_server_side (void **ctx, ...@@ -413,19 +453,30 @@ void setup_context_and_server_side (void **ctx,
void shutdown_context_and_server_side (void *ctx, void shutdown_context_and_server_side (void *ctx,
void *zap_thread, void *zap_thread,
void *server, void *server,
void *server_mon) void *server_mon,
void *handler)
{ {
int rc = s_send (handler, "STOP");
assert (rc == 4);
char *buf = s_recv (handler);
assert (buf);
assert (streq (buf, "STOPPED"));
free (buf);
rc = zmq_unbind (handler, "inproc://handler-control");
assert (rc == 0);
close_zero_linger (handler);
#ifdef ZMQ_BUILD_DRAFT_API #ifdef ZMQ_BUILD_DRAFT_API
close_zero_linger (server_mon); close_zero_linger (server_mon);
#endif #endif
close_zero_linger (server); close_zero_linger (server);
int rc = zmq_ctx_term (ctx);
assert (rc == 0);
// Wait until ZAP handler terminates // Wait until ZAP handler terminates
zmq_threadclose (zap_thread); zmq_threadclose (zap_thread);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
zmq_atomic_counter_destroy (&zap_requests_handled); zmq_atomic_counter_destroy (&zap_requests_handled);
} }
...@@ -635,7 +686,8 @@ int main (void) ...@@ -635,7 +686,8 @@ int main (void)
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_curve_security_with_valid_credentials (ctx, my_endpoint, server, test_curve_security_with_valid_credentials (ctx, my_endpoint, server,
server_mon, timeout); server_mon, timeout);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
char garbage_key [] = "0000000000000000000000000000000000000000"; char garbage_key [] = "0000000000000000000000000000000000000000";
...@@ -646,7 +698,8 @@ int main (void) ...@@ -646,7 +698,8 @@ int main (void)
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, garbage_key, test_garbage_key (ctx, server, server_mon, my_endpoint, garbage_key,
valid_client_public, valid_client_secret); valid_client_public, valid_client_secret);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// Check CURVE security with a garbage client public key // Check CURVE security with a garbage client public key
// This will be caught by the curve_server class, not passed to ZAP // This will be caught by the curve_server class, not passed to ZAP
...@@ -655,7 +708,8 @@ int main (void) ...@@ -655,7 +708,8 @@ int main (void)
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public, test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public,
garbage_key, valid_client_secret); garbage_key, valid_client_secret);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// Check CURVE security with a garbage client secret key // Check CURVE security with a garbage client secret key
// This will be caught by the curve_server class, not passed to ZAP // This will be caught by the curve_server class, not passed to ZAP
...@@ -664,30 +718,35 @@ int main (void) ...@@ -664,30 +718,35 @@ int main (void)
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public, test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public,
valid_client_public, garbage_key); valid_client_public, garbage_key);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_curve_security_with_bogus_client_credentials (ctx, my_endpoint, server, test_curve_security_with_bogus_client_credentials (ctx, my_endpoint, server,
server_mon, timeout); server_mon, timeout);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_curve_security_with_null_client_credentials (ctx, my_endpoint, server, test_curve_security_with_null_client_credentials (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_curve_security_with_plain_client_credentials (ctx, my_endpoint, server, test_curve_security_with_plain_client_credentials (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
&server_mon, my_endpoint); &server_mon, my_endpoint);
test_curve_security_unauthenticated_message (my_endpoint, server, timeout); test_curve_security_unauthenticated_message (my_endpoint, server, timeout);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// Invalid ZAP protocol tests // Invalid ZAP protocol tests
...@@ -697,7 +756,8 @@ int main (void) ...@@ -697,7 +756,8 @@ int main (void)
&zap_handler_wrong_version); &zap_handler_wrong_version);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server, test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// wrong request id // wrong request id
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
...@@ -705,7 +765,8 @@ int main (void) ...@@ -705,7 +765,8 @@ int main (void)
&zap_handler_wrong_request_id); &zap_handler_wrong_request_id);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server, test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// status invalid (not a 3-digit number) // status invalid (not a 3-digit number)
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
...@@ -713,7 +774,8 @@ int main (void) ...@@ -713,7 +774,8 @@ int main (void)
&zap_handler_wrong_status_invalid); &zap_handler_wrong_status_invalid);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server, test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// too many parts // too many parts
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server, setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
...@@ -721,7 +783,8 @@ int main (void) ...@@ -721,7 +783,8 @@ int main (void)
&zap_handler_too_many_parts); &zap_handler_too_many_parts);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server, test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
server_mon); server_mon);
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
// ZAP non-standard cases // ZAP non-standard cases
...@@ -740,7 +803,8 @@ int main (void) ...@@ -740,7 +803,8 @@ int main (void)
0, 0 0, 0
#endif #endif
); );
shutdown_context_and_server_side (ctx, zap_thread, server, server_mon); shutdown_context_and_server_side (ctx, zap_thread, server, server_mon,
handler);
ctx = zmq_ctx_new (); ctx = zmq_ctx_new ();
test_curve_security_invalid_keysize (ctx); test_curve_security_invalid_keysize (ctx);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment