0
0
mirror of https://github.com/zeromq/libzmq.git synced 2024-12-27 07:31:03 +08:00

Merge pull request #2659 from bluca/fix_getrandom

Problems: test_security_curve occasionally hangs or fails due to ECONNABORTED
This commit is contained in:
Jim Klimov 2017-08-07 12:36:59 +02:00 committed by GitHub
commit 612d81a831

View File

@ -148,13 +148,42 @@ enum zap_protocol_t
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
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);
if (!version)
break; // Terminating
break; // Terminating - peer's socket closed
char *sequence = s_recv (handler);
char *domain = s_recv (handler);
@ -206,37 +235,43 @@ static void zap_handler_generic (void *handler, zap_protocol_t zap_protocol)
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,
@ -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
// via the specified socket monitor
// returns the number of occurrences of the expected event
// interrupts, if a ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL/EPIPE/ECONNRESET
// occurs; in this case, 0 is returned
// interrupts, if a ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL with EPIPE, ECONNRESET
// or ECONNABORTED occurs; in this case, 0 is returned
// this should be investigated further, see
// https://github.com/zeromq/libzmq/issues/2644
int expect_monitor_event_multiple (void *server_mon,
@ -295,11 +330,12 @@ int expect_monitor_event_multiple (void *server_mon,
!= -1) {
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
// 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 &&
(err == EPIPE || err == ECONNRESET)) {
(err == EPIPE || err == ECONNRESET || err == ECONNABORTED)) {
fprintf (stderr, "Ignored event: %x (err = %i)\n", event, err);
client_closed_connection = 1;
break;
@ -360,13 +396,17 @@ void setup_context_and_server_side (void **ctx,
zap_requests_handled = zmq_atomic_counter_new ();
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);
assert (*handler);
int rc = zmq_bind (*handler, "inproc://zeromq.zap.01");
int rc = zmq_bind (*handler, "inproc://handler-control");
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 = zmq_socket (*ctx, ZMQ_DEALER);
@ -413,19 +453,30 @@ void setup_context_and_server_side (void **ctx,
void shutdown_context_and_server_side (void *ctx,
void *zap_thread,
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
close_zero_linger (server_mon);
#endif
close_zero_linger (server);
int rc = zmq_ctx_term (ctx);
assert (rc == 0);
// Wait until ZAP handler terminates
zmq_threadclose (zap_thread);
rc = zmq_ctx_term (ctx);
assert (rc == 0);
zmq_atomic_counter_destroy (&zap_requests_handled);
}
@ -635,7 +686,8 @@ int main (void)
&server_mon, my_endpoint);
test_curve_security_with_valid_credentials (ctx, my_endpoint, server,
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";
@ -646,7 +698,8 @@ int main (void)
&server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, garbage_key,
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
// This will be caught by the curve_server class, not passed to ZAP
@ -655,7 +708,8 @@ int main (void)
&server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public,
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
// This will be caught by the curve_server class, not passed to ZAP
@ -664,30 +718,35 @@ int main (void)
&server_mon, my_endpoint);
test_garbage_key (ctx, server, server_mon, my_endpoint, valid_server_public,
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,
&server_mon, my_endpoint);
test_curve_security_with_bogus_client_credentials (ctx, my_endpoint, server,
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,
&server_mon, my_endpoint);
test_curve_security_with_null_client_credentials (ctx, my_endpoint, server,
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,
&server_mon, my_endpoint);
test_curve_security_with_plain_client_credentials (ctx, my_endpoint, server,
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,
&server_mon, my_endpoint);
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
@ -697,7 +756,8 @@ int main (void)
&zap_handler_wrong_version);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
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
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
@ -705,7 +765,8 @@ int main (void)
&zap_handler_wrong_request_id);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
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)
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
@ -713,7 +774,8 @@ int main (void)
&zap_handler_wrong_status_invalid);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
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
setup_context_and_server_side (&ctx, &handler, &zap_thread, &server,
@ -721,7 +783,8 @@ int main (void)
&zap_handler_too_many_parts);
test_curve_security_zap_protocol_error (ctx, my_endpoint, server,
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
@ -740,7 +803,8 @@ int main (void)
0, 0
#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 ();
test_curve_security_invalid_keysize (ctx);