aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2013-08-13 00:58:14 +0000
committerFlorian Dold <florian.dold@gmail.com>2013-08-13 00:58:14 +0000
commit84701f040c57bee43892fa0d079344c1a9e48dc3 (patch)
tree032b74a52f89c407114f444106eb24703d811149
parentc1c986c8827d66cd20923b17ba1f5103d673e5ea (diff)
downloadgnunet-84701f040c57bee43892fa0d079344c1a9e48dc3.tar.gz
gnunet-84701f040c57bee43892fa0d079344c1a9e48dc3.zip
- proper shutdown sequence for set makes consensus happy
-rw-r--r--src/consensus/gnunet-service-consensus.c2
-rw-r--r--src/include/gnunet_protocols.h5
-rw-r--r--src/set/gnunet-service-set.c25
-rw-r--r--src/set/gnunet-service-set_union.c43
-rw-r--r--src/set/test_set_api.c1
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
291set_destroy (struct Set *set) 291set_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 */
1074static void 1086static void
1075peer_done_sent_cb (void *cls) 1087handle_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
1090handle_p2p_done (void *cls, const struct GNUNET_MessageHeader *mh) 1102handle_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);