diff options
author | Florian Dold <florian.dold@gmail.com> | 2013-08-13 00:58:14 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2013-08-13 00:58:14 +0000 |
commit | 84701f040c57bee43892fa0d079344c1a9e48dc3 (patch) | |
tree | 032b74a52f89c407114f444106eb24703d811149 | |
parent | c1c986c8827d66cd20923b17ba1f5103d673e5ea (diff) | |
download | gnunet-84701f040c57bee43892fa0d079344c1a9e48dc3.tar.gz gnunet-84701f040c57bee43892fa0d079344c1a9e48dc3.zip |
- proper shutdown sequence for set makes consensus happy
-rw-r--r-- | src/consensus/gnunet-service-consensus.c | 2 | ||||
-rw-r--r-- | src/include/gnunet_protocols.h | 5 | ||||
-rw-r--r-- | src/set/gnunet-service-set.c | 25 | ||||
-rw-r--r-- | src/set/gnunet-service-set_union.c | 43 | ||||
-rw-r--r-- | src/set/test_set_api.c | 1 |
5 files changed, 52 insertions, 24 deletions
diff --git a/src/consensus/gnunet-service-consensus.c b/src/consensus/gnunet-service-consensus.c index 274b6f839..a14eddebe 100644 --- a/src/consensus/gnunet-service-consensus.c +++ b/src/consensus/gnunet-service-consensus.c | |||
@@ -968,6 +968,8 @@ set_listen_cb (void *cls, | |||
968 | } | 968 | } |
969 | break; | 969 | break; |
970 | default: | 970 | default: |
971 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "P%d got unexpected set request in round %d from P%d\n", | ||
972 | session->local_peer_idx, session->current_round, index); | ||
971 | GNUNET_break_op (0); | 973 | GNUNET_break_op (0); |
972 | return; | 974 | return; |
973 | } | 975 | } |
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h index 5c59f36f4..76655b697 100644 --- a/src/include/gnunet_protocols.h +++ b/src/include/gnunet_protocols.h | |||
@@ -1784,6 +1784,11 @@ extern "C" | |||
1784 | */ | 1784 | */ |
1785 | #define GNUNET_MESSAGE_TYPE_SET_ITER_DONE 589 | 1785 | #define GNUNET_MESSAGE_TYPE_SET_ITER_DONE 589 |
1786 | 1786 | ||
1787 | /** | ||
1788 | * Iteration end marker for the client. | ||
1789 | */ | ||
1790 | #define GNUNET_MESSAGE_TYPE_SET_P2P_DIE 590 | ||
1791 | |||
1787 | 1792 | ||
1788 | 1793 | ||
1789 | /******************************************************************************* | 1794 | /******************************************************************************* |
diff --git a/src/set/gnunet-service-set.c b/src/set/gnunet-service-set.c index 9210e1ea8..fa6fb5a6b 100644 --- a/src/set/gnunet-service-set.c +++ b/src/set/gnunet-service-set.c | |||
@@ -291,7 +291,9 @@ static void | |||
291 | set_destroy (struct Set *set) | 291 | set_destroy (struct Set *set) |
292 | { | 292 | { |
293 | /* If the client is not dead yet, destroy it. | 293 | /* If the client is not dead yet, destroy it. |
294 | * The client's destroy callback will destroy the set again. */ | 294 | * The client's destroy callback will destroy the set again. |
295 | * We do this so that the tunnel end handler still has a valid set handle | ||
296 | * to destroy. */ | ||
295 | if (NULL != set->client) | 297 | if (NULL != set->client) |
296 | { | 298 | { |
297 | struct GNUNET_SERVER_Client *client = set->client; | 299 | struct GNUNET_SERVER_Client *client = set->client; |
@@ -299,11 +301,20 @@ set_destroy (struct Set *set) | |||
299 | GNUNET_SERVER_client_disconnect (client); | 301 | GNUNET_SERVER_client_disconnect (client); |
300 | return; | 302 | return; |
301 | } | 303 | } |
304 | GNUNET_assert (NULL != set->state); | ||
305 | set->vt->destroy_set (set->state); | ||
306 | set->state = NULL; | ||
302 | if (NULL != set->client_mq) | 307 | if (NULL != set->client_mq) |
303 | { | 308 | { |
304 | GNUNET_MQ_destroy (set->client_mq); | 309 | GNUNET_MQ_destroy (set->client_mq); |
305 | set->client_mq = NULL; | 310 | set->client_mq = NULL; |
306 | } | 311 | } |
312 | if (NULL != set->iter) | ||
313 | { | ||
314 | GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter); | ||
315 | set->iter = NULL; | ||
316 | } | ||
317 | GNUNET_CONTAINER_DLL_remove (sets_head, sets_tail, set); | ||
307 | if (NULL != set->elements) | 318 | if (NULL != set->elements) |
308 | { | 319 | { |
309 | GNUNET_CONTAINER_multihashmap_iterate (set->elements, | 320 | GNUNET_CONTAINER_multihashmap_iterate (set->elements, |
@@ -311,15 +322,6 @@ set_destroy (struct Set *set) | |||
311 | GNUNET_CONTAINER_multihashmap_destroy (set->elements); | 322 | GNUNET_CONTAINER_multihashmap_destroy (set->elements); |
312 | set->elements = NULL; | 323 | set->elements = NULL; |
313 | } | 324 | } |
314 | if (NULL != set->iter) | ||
315 | { | ||
316 | GNUNET_CONTAINER_multihashmap_iterator_destroy (set->iter); | ||
317 | set->iter = NULL; | ||
318 | } | ||
319 | GNUNET_assert (NULL != set->state); | ||
320 | set->vt->destroy_set (set->state); | ||
321 | set->state = NULL; | ||
322 | GNUNET_CONTAINER_DLL_remove (sets_head, sets_tail, set); | ||
323 | GNUNET_free (set); | 325 | GNUNET_free (set); |
324 | } | 326 | } |
325 | 327 | ||
@@ -1079,7 +1081,7 @@ dispatch_p2p_message (void *cls, | |||
1079 | 1081 | ||
1080 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dispatching mesh message (type: %u)\n", | 1082 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "dispatching mesh message (type: %u)\n", |
1081 | ntohs (message->type)); | 1083 | ntohs (message->type)); |
1082 | /* FIXME: do this before or after the handler? */ | 1084 | /* do this before the handler, as the handler might kill the tunnel */ |
1083 | GNUNET_MESH_receive_done (tunnel); | 1085 | GNUNET_MESH_receive_done (tunnel); |
1084 | ret = tc->vt->msg_handler (tc->op, message); | 1086 | ret = tc->vt->msg_handler (tc->op, message); |
1085 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handled mesh message (type: %u)\n", | 1087 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "handled mesh message (type: %u)\n", |
@@ -1124,6 +1126,7 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
1124 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_IBF, 0}, | 1126 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_IBF, 0}, |
1125 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 0}, | 1127 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENTS, 0}, |
1126 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DONE, 0}, | 1128 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DONE, 0}, |
1129 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_DIE, 0}, | ||
1127 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0}, | 1130 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_ELEMENT_REQUESTS, 0}, |
1128 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_SE, 0}, | 1131 | {dispatch_p2p_message, GNUNET_MESSAGE_TYPE_SET_P2P_SE, 0}, |
1129 | {NULL, 0, 0} | 1132 | {NULL, 0, 0} |
diff --git a/src/set/gnunet-service-set_union.c b/src/set/gnunet-service-set_union.c index e48386492..0e58e71ce 100644 --- a/src/set/gnunet-service-set_union.c +++ b/src/set/gnunet-service-set_union.c | |||
@@ -180,6 +180,11 @@ struct OperationState | |||
180 | * a linked list. | 180 | * a linked list. |
181 | */ | 181 | */ |
182 | struct OperationState *prev; | 182 | struct OperationState *prev; |
183 | |||
184 | /** | ||
185 | * Did we send the client that we are done? | ||
186 | */ | ||
187 | int client_done_sent; | ||
183 | }; | 188 | }; |
184 | 189 | ||
185 | 190 | ||
@@ -981,12 +986,17 @@ send_client_done_and_destroy (struct OperationState *eo) | |||
981 | struct GNUNET_MQ_Envelope *ev; | 986 | struct GNUNET_MQ_Envelope *ev; |
982 | struct GNUNET_SET_ResultMessage *rm; | 987 | struct GNUNET_SET_ResultMessage *rm; |
983 | 988 | ||
989 | GNUNET_assert (GNUNET_NO == eo->client_done_sent); | ||
990 | |||
991 | eo->client_done_sent = GNUNET_YES; | ||
992 | |||
984 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); | 993 | ev = GNUNET_MQ_msg (rm, GNUNET_MESSAGE_TYPE_SET_RESULT); |
985 | rm->request_id = htonl (eo->spec->client_request_id); | 994 | rm->request_id = htonl (eo->spec->client_request_id); |
986 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); | 995 | rm->result_status = htons (GNUNET_SET_STATUS_DONE); |
987 | rm->element_type = htons (0); | 996 | rm->element_type = htons (0); |
988 | GNUNET_MQ_send (eo->spec->set->client_mq, ev); | 997 | GNUNET_MQ_send (eo->spec->set->client_mq, ev); |
989 | 998 | ||
999 | union_operation_destroy (eo); | ||
990 | } | 1000 | } |
991 | 1001 | ||
992 | 1002 | ||
@@ -1067,12 +1077,14 @@ handle_p2p_element_requests (void *cls, const struct GNUNET_MessageHeader *mh) | |||
1067 | 1077 | ||
1068 | 1078 | ||
1069 | /** | 1079 | /** |
1070 | * Callback used for notifications | 1080 | * Handle a 'DIE' message from the remote peer. |
1071 | * | 1081 | * This indicates that the other peer is terminated. |
1072 | * @param cls closure | 1082 | * |
1083 | * @param cls the union operation | ||
1084 | * @param mh the message | ||
1073 | */ | 1085 | */ |
1074 | static void | 1086 | static void |
1075 | peer_done_sent_cb (void *cls) | 1087 | handle_p2p_die (void *cls, const struct GNUNET_MessageHeader *mh) |
1076 | { | 1088 | { |
1077 | struct OperationState *eo = cls; | 1089 | struct OperationState *eo = cls; |
1078 | 1090 | ||
@@ -1090,22 +1102,24 @@ static void | |||
1090 | handle_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh) | 1102 | handle_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh) |
1091 | { | 1103 | { |
1092 | struct OperationState *eo = cls; | 1104 | struct OperationState *eo = cls; |
1105 | struct GNUNET_MQ_Envelope *ev; | ||
1093 | 1106 | ||
1094 | if (eo->phase == PHASE_EXPECT_ELEMENTS_AND_REQUESTS) | 1107 | if (eo->phase == PHASE_EXPECT_ELEMENTS_AND_REQUESTS) |
1095 | { | 1108 | { |
1096 | /* we got all requests, but still have to send our elements as response */ | 1109 | /* we got all requests, but still have to send our elements as response */ |
1097 | struct GNUNET_MQ_Envelope *ev; | ||
1098 | 1110 | ||
1099 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got DONE, sending final DONE after elements\n"); | 1111 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got DONE, sending final DONE after elements\n"); |
1100 | eo->phase = PHASE_FINISHED; | 1112 | eo->phase = PHASE_FINISHED; |
1101 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DONE); | 1113 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DONE); |
1102 | GNUNET_MQ_notify_sent (ev, peer_done_sent_cb, eo); | ||
1103 | GNUNET_MQ_send (eo->mq, ev); | 1114 | GNUNET_MQ_send (eo->mq, ev); |
1104 | return; | 1115 | return; |
1105 | } | 1116 | } |
1106 | if (eo->phase == PHASE_EXPECT_ELEMENTS) | 1117 | if (eo->phase == PHASE_EXPECT_ELEMENTS) |
1107 | { | 1118 | { |
1108 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got final DONE\n"); | 1119 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got final DONE, trying to send DIE\n"); |
1120 | /* send the die message, which might not even be delivered, | ||
1121 | * as we could have shut down before that */ | ||
1122 | ev = GNUNET_MQ_msg_header (GNUNET_MESSAGE_TYPE_SET_P2P_DIE); | ||
1109 | eo->phase = PHASE_FINISHED; | 1123 | eo->phase = PHASE_FINISHED; |
1110 | send_client_done_and_destroy (eo); | 1124 | send_client_done_and_destroy (eo); |
1111 | return; | 1125 | return; |
@@ -1290,6 +1304,9 @@ union_handle_p2p_message (struct OperationState *eo, | |||
1290 | case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: | 1304 | case GNUNET_MESSAGE_TYPE_SET_P2P_DONE: |
1291 | handle_p2p_done (eo, mh); | 1305 | handle_p2p_done (eo, mh); |
1292 | break; | 1306 | break; |
1307 | case GNUNET_MESSAGE_TYPE_SET_P2P_DIE: | ||
1308 | handle_p2p_die (eo, mh); | ||
1309 | break; | ||
1293 | default: | 1310 | default: |
1294 | /* something wrong with mesh's message handlers? */ | 1311 | /* something wrong with mesh's message handlers? */ |
1295 | GNUNET_assert (0); | 1312 | GNUNET_assert (0); |
@@ -1314,18 +1331,20 @@ union_peer_disconnect (struct OperationState *op) | |||
1314 | { | 1331 | { |
1315 | struct GNUNET_MQ_Envelope *ev; | 1332 | struct GNUNET_MQ_Envelope *ev; |
1316 | struct GNUNET_SET_ResultMessage *msg; | 1333 | struct GNUNET_SET_ResultMessage *msg; |
1334 | |||
1317 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); | 1335 | ev = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_SET_RESULT); |
1318 | msg->request_id = htonl (op->spec->client_request_id); | 1336 | msg->request_id = htonl (op->spec->client_request_id); |
1319 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); | 1337 | msg->result_status = htons (GNUNET_SET_STATUS_FAILURE); |
1320 | msg->element_type = htons (0); | 1338 | msg->element_type = htons (0); |
1321 | GNUNET_MQ_send (op->spec->set->client_mq, ev); | 1339 | GNUNET_MQ_send (op->spec->set->client_mq, ev); |
1322 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "other peer disconnected prematurely\n"); | 1340 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "other peer disconnected prematurely\n"); |
1341 | union_operation_destroy (op); | ||
1342 | return; | ||
1323 | } | 1343 | } |
1324 | else | 1344 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "other peer disconnected (finished)\n"); |
1325 | { | 1345 | /* maybe the other peer did not get to send his 'DIE' message before he died? */ |
1326 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "other peer disconnected (finished)\n"); | 1346 | if (GNUNET_NO == op->client_done_sent) |
1327 | } | 1347 | send_client_done_and_destroy (op); |
1328 | union_operation_destroy (op); | ||
1329 | } | 1348 | } |
1330 | 1349 | ||
1331 | 1350 | ||
diff --git a/src/set/test_set_api.c b/src/set/test_set_api.c index 6085c59f3..3dd49f036 100644 --- a/src/set/test_set_api.c +++ b/src/set/test_set_api.c | |||
@@ -232,7 +232,6 @@ run (void *cls, | |||
232 | 232 | ||
233 | test_iter (); | 233 | test_iter (); |
234 | 234 | ||
235 | return; | ||
236 | set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); | 235 | set1 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); |
237 | set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); | 236 | set2 = GNUNET_SET_create (cfg, GNUNET_SET_OPERATION_UNION); |
238 | GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); | 237 | GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK, &app_id); |