diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-16 14:05:48 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-09-16 14:05:48 +0000 |
commit | 77139316eeecda84e45710d4dfd7c74dcff47942 (patch) | |
tree | 79902e46fb92f29523bbaad730b15679ca31b10f /src/testbed | |
parent | b9a26a3891508c9891ca2ceb142caef2e3b08f31 (diff) | |
download | gnunet-77139316eeecda84e45710d4dfd7c74dcff47942.tar.gz gnunet-77139316eeecda84e45710d4dfd7c74dcff47942.zip |
- fix crash when disconnecting from misbehaving client
Diffstat (limited to 'src/testbed')
-rw-r--r-- | src/testbed/barriers.README.org | 118 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_barriers.c | 10 | ||||
-rw-r--r-- | src/testbed/test_testbed_api_barriers.conf | 2 |
3 files changed, 66 insertions, 64 deletions
diff --git a/src/testbed/barriers.README.org b/src/testbed/barriers.README.org index ed39903c0..40488a0cc 100644 --- a/src/testbed/barriers.README.org +++ b/src/testbed/barriers.README.org | |||
@@ -1,87 +1,93 @@ | |||
1 | * Description | 1 | * Description |
2 | The testbed's barriers API facilitates coordination among the peers run by the | 2 | The testbed subsystem's barriers API facilitates coordination among the peers |
3 | testbed and the experiment driver. The concept is similar to the barrier | 3 | run by the testbed and the experiment driver. The concept is similar to the |
4 | synchronisation mechanism found in parallel programming or multithreading | 4 | barrier synchronisation mechanism found in parallel programming or |
5 | paradigms - a peer waits at a barrier upon reaching it until the barrier is | 5 | multi-threading paradigms - a peer waits at a barrier upon reaching it until the |
6 | crossed i.e, the barrier is reached by a predefined number of peers. This | 6 | barrier is reached by a predefined number of peers. This predefined number of |
7 | predefined number peers required to cross a barrier is also called quorum. We | 7 | peers required to cross a barrier is also called quorum. We say a peer has |
8 | say a peer has reached a barrier if the peer is waiting for the barrier to be | 8 | reached a barrier if the peer is waiting for the barrier to be crossed. |
9 | crossed. Similarly a barrier is said to be reached if the required quorum of | 9 | Similarly a barrier is said to be reached if the required quorum of peers reach |
10 | peers reach the barrier. | 10 | the barrier. A barrier which is reached is deemed as crossed after all the |
11 | peers waiting on it are notified. | ||
11 | 12 | ||
12 | The barriers API provides the following functions: | 13 | The barriers API provides the following functions: |
14 | 1) GNUNET_TESTBED_barrier_init(): function to initialse a barrier in the | ||
15 | experiment | ||
16 | 2) GNUNET_TESTBED_barrier_cancel(): function to cancel a barrier which has been | ||
17 | initialised before | ||
18 | 3) GNUNET_TESTBED_barrier_wait(): function to signal barrier service that the | ||
19 | caller has reached a barrier and is waiting for it to be crossed | ||
20 | 4) GNUNET_TESTBED_barrier_wait_cancel(): function to stop waiting for a barrier | ||
21 | to be crossed | ||
13 | 22 | ||
14 | 1) barrier_init(): function to initialse a barrier in the experiment | 23 | Among the above functions, the first two, namely GNUNET_TESTBED_barrier_init() |
15 | 2) barrier_cancel(): function to cancel a barrier which has been initialised | 24 | and GNUNET_TESTBED_barrier_cacel() are used by experiment drivers. All barriers |
16 | before | 25 | should be initialised by the experiment driver by calling |
17 | 3) barrier_wait(): function to signal barrier service that the caller has reached | 26 | GNUNET_TESTBED_barrier_init(). This function takes a name to identify the |
18 | a barrier and is waiting for it to be crossed | 27 | barrier, the quorum required for the barrier to be crossed and a notification |
19 | 4) barrier_wait_cancel(): function to stop waiting for a barrier to be crossed | 28 | callback for notifying the experiment driver when the barrier is crossed. The |
29 | GNUNET_TESTBED_function barrier_cancel() cancels an initialised barrier and | ||
30 | frees the resources allocated for it. This function can be called upon a | ||
31 | initialised barrier before it is crossed. | ||
20 | 32 | ||
21 | Among the above functions, the first two, namely barrier_init() and | 33 | The remaining two functions GNUNET_TESTBED_barrier_wait() and |
22 | barrier_cacel() are used by experiment drivers. All barriers should be | 34 | GNUNET_TESTBED_barrier_wait_cancel() are used in the peer's processes. |
23 | initialised by the experiment driver by calling barrier_init(). This function | 35 | GNUNET_TESTBED_barrier_wait() connects to the local barrier service running on |
24 | takes a name to identify the barrier, the quorum required for the barrier to be | 36 | the same host the peer is running on and registers that the caller has reached |
25 | crossed and a notification callback for notifying the experiment driver when the | 37 | the barrier and is waiting for the barrier to be crossed. Note that this |
26 | barrier is crossed. The function barrier_cancel() cancels an initialised | 38 | function can only be used by peers which are started by testbed as this function |
27 | barrier and frees the resources allocated for it. This function can be called | 39 | tries to access the local barrier service which is part of the testbed |
28 | upon a initialised barrier before it is crossed. | 40 | controller service. Calling GNUNET_TESTBED_barrier_wait() on an uninitialised |
29 | 41 | barrier results in failure. GNUNET_TESTBED_barrier_wait_cancel() cancels the | |
30 | The remaining two functions barrier_wait() and barrier_wait_cancel() are used in | 42 | notification registered by GNUNET_TESTBED_barrier_wait(). |
31 | the peer's processes. barrier_wait() connects to the local barrier service | ||
32 | running on the same host the peer is running on and registers that the caller | ||
33 | has reached the barrier and is waiting for the barrier to be crossed. Note that | ||
34 | this function can only be used by peers which are started by testbed as this | ||
35 | function tries to access the local barrier service which is part of the testbed | ||
36 | controller service. Calling barrier_wait() on an uninitialised barrier barrier | ||
37 | results in failure. barrier_wait_cancel() cancels the notification registered | ||
38 | by barrier_wait(). | ||
39 | 43 | ||
40 | 44 | ||
41 | * Implementation | 45 | * Implementation |
42 | Since barriers involve coordination between experiment driver and peers, the | 46 | Since barriers involve coordination between experiment driver and peers, the |
43 | barrier service in the testbed controller is split into two components. The | 47 | barrier service in the testbed controller is split into two components. The |
44 | first component responds to the message generated by the barrier API used by the | 48 | first component responds to the message generated by the barrier API used by the |
45 | experiment driver (functions barrier_init() and barrier_cancel()) and the second | 49 | experiment driver (functions GNUNET_TESTBED_barrier_init() and |
46 | component to the messages generated by barrier API used by peers (functions | 50 | GNUNET_TESTBED_barrier_cancel()) and the second component to the messages |
47 | barrier_wait() and barrier_wait_cancel()) | 51 | generated by barrier API used by peers (functions GNUNET_TESTBED_barrier_wait() |
52 | and GNUNET_TESTBED_barrier_wait_cancel()). | ||
48 | 53 | ||
49 | Calling barrier_init() sends a BARRIER_INIT message to the master controller. | 54 | Calling GNUNET_TESTBED_barrier_init() sends a BARRIER_INIT message to the master |
50 | The master controller then registers a barrier and calls barrier_init() for each | 55 | controller. The master controller then registers a barrier and calls |
51 | its subcontrollers. In this way barrier initialisation is propagated to the | 56 | GNUNET_TESTBED_barrier_init() for each its subcontrollers. In this way barrier |
52 | controller hierarchy. While propagating initialisation, any errors at a | 57 | initialisation is propagated to the controller hierarchy. While propagating |
53 | subcontroller such as timeout during further propagation are reported up the | 58 | initialisation, any errors at a subcontroller such as timeout during further |
54 | hierarchy back to the experiment driver. | 59 | propagation are reported up the hierarchy back to the experiment driver. |
55 | 60 | ||
56 | Similar to barrier_init(), barrier_cancel() propagates BARRIER_CANCEL message | 61 | Similar to GNUNET_TESTBED_barrier_init(), GNUNET_TESTBED_barrier_cancel() |
57 | which causes controllers to remove an initialised barrier. | 62 | propagates BARRIER_CANCEL message which causes controllers to remove an |
63 | initialised barrier. | ||
58 | 64 | ||
59 | The second component is implemented as a separate service in the binary | 65 | The second component is implemented as a separate service in the binary |
60 | `gnunet-service-testbed' which already has the testbed controller service. | 66 | `gnunet-service-testbed' which already has the testbed controller service. |
61 | Although this deviates from the gnunet process architecture of having one | 67 | Although this deviates from the gnunet process architecture of having one |
62 | service per binary, it is needed in this case as this component needs access to | 68 | service per binary, it is needed in this case as this component needs access to |
63 | barrier data created by the first component. This component responds to | 69 | barrier data created by the first component. This component responds to |
64 | BARRIER_WAIT messages from local peers when they call barrier_wait(). Upon | 70 | BARRIER_WAIT messages from local peers when they call |
65 | receiving BARRIER_WAIT message, the service checks if the requested barrier has | 71 | GNUNET_TESTBED_barrier_wait(). Upon receiving BARRIER_WAIT message, the service |
66 | been initialised before and if it was not initialised, an error status is sent | 72 | checks if the requested barrier has been initialised before and if it was not |
67 | through BARRIER_STATUS message to the local peer and the connection from the | 73 | initialised, an error status is sent through BARRIER_STATUS message to the local |
68 | peer is terminated. If the barrier is initialised before, the barrier's counter | 74 | peer and the connection from the peer is terminated. If the barrier is |
69 | for reached peers is incremented and a notification is registered to notify the | 75 | initialised before, the barrier's counter for reached peers is incremented and a |
70 | peer when the barrier is reached. The connection from the peer is left open. | 76 | notification is registered to notify the peer when the barrier is reached. The |
77 | connection from the peer is left open. | ||
71 | 78 | ||
72 | When enough peers required to attain the quorum send BARRIER_WAIT messages, the | 79 | When enough peers required to attain the quorum send BARRIER_WAIT messages, the |
73 | controller sends a BARRIER_STATUS message to its parent informing that the | 80 | controller sends a BARRIER_STATUS message to its parent informing that the |
74 | barrier is crossed. If the controller has started further subcontrollers, it | 81 | barrier is crossed. If the controller has started further subcontrollers, it |
75 | delays this message until it receives a notification from each of those | 82 | delays this message until it receives a similar notification from each of those |
76 | subcontrollers that the barrier is crossed. Finally, the barriers API at the | 83 | subcontrollers. Finally, the barriers API at the experiment driver receives the |
77 | experiment driver receives the BARRIER_STATUS when the barrier is reached at all | 84 | BARRIER_STATUS when the barrier is reached at all the controllers. |
78 | the controllers. | ||
79 | 85 | ||
80 | The barriers API at the experiment driver responds to the BARRIER_STATUS message | 86 | The barriers API at the experiment driver responds to the BARRIER_STATUS message |
81 | by echoing it back to the master controller and notifying the experiment | 87 | by echoing it back to the master controller and notifying the experiment |
82 | controller through the notification callback that a barrier has been crossed. | 88 | controller through the notification callback that a barrier has been crossed. |
83 | The echoed BARRIER_STATUS message is propagated by the master controller to the | 89 | The echoed BARRIER_STATUS message is propagated by the master controller to the |
84 | controller hierarchy. This progation triggers the notifications registered by | 90 | controller hierarchy. This propagation triggers the notifications registered by |
85 | peers at each of the controllers in the hierarchy. Note the difference between | 91 | peers at each of the controllers in the hierarchy. Note the difference between |
86 | this downward propagation of the BARRIER_STATUS message from its upward | 92 | this downward propagation of the BARRIER_STATUS message from its upward |
87 | propagation -- the upward propagation is needed for ensuring that the barrier is | 93 | propagation -- the upward propagation is needed for ensuring that the barrier is |
diff --git a/src/testbed/gnunet-service-testbed_barriers.c b/src/testbed/gnunet-service-testbed_barriers.c index 68011065d..5668d03cf 100644 --- a/src/testbed/gnunet-service-testbed_barriers.c +++ b/src/testbed/gnunet-service-testbed_barriers.c | |||
@@ -360,13 +360,7 @@ remove_barrier (struct Barrier *barrier) | |||
360 | while (NULL != (ctx = barrier->head)) | 360 | while (NULL != (ctx = barrier->head)) |
361 | { | 361 | { |
362 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); | 362 | GNUNET_CONTAINER_DLL_remove (barrier->head, barrier->tail, ctx); |
363 | GNUNET_SERVER_client_drop (ctx->client); | 363 | cleanup_clientctx (ctx); |
364 | ctx->client = NULL; | ||
365 | if (NULL != ctx->tx) | ||
366 | { | ||
367 | GNUNET_SERVER_notify_transmit_ready_cancel (ctx->tx); | ||
368 | ctx->tx = NULL; | ||
369 | } | ||
370 | } | 364 | } |
371 | GNUNET_free (barrier->name); | 365 | GNUNET_free (barrier->name); |
372 | GNUNET_SERVER_client_drop (barrier->mc); | 366 | GNUNET_SERVER_client_drop (barrier->mc); |
@@ -532,6 +526,8 @@ disconnect_cb (void *cls, struct GNUNET_SERVER_Client *client) | |||
532 | if (NULL == client) | 526 | if (NULL == client) |
533 | return; | 527 | return; |
534 | client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); | 528 | client_ctx = GNUNET_SERVER_client_get_user_context (client, struct ClientCtx); |
529 | if (NULL == client_ctx) | ||
530 | return; | ||
535 | cleanup_clientctx (client_ctx); | 531 | cleanup_clientctx (client_ctx); |
536 | } | 532 | } |
537 | 533 | ||
diff --git a/src/testbed/test_testbed_api_barriers.conf b/src/testbed/test_testbed_api_barriers.conf index 758cbd8c9..056cfac22 100644 --- a/src/testbed/test_testbed_api_barriers.conf +++ b/src/testbed/test_testbed_api_barriers.conf | |||
@@ -13,7 +13,7 @@ PORT = 12366 | |||
13 | [test-barriers] | 13 | [test-barriers] |
14 | AUTOSTART = YES | 14 | AUTOSTART = YES |
15 | PORT = 12114 #not really used | 15 | PORT = 12114 #not really used |
16 | BINARY = gnunet-service-test-barriers | 16 | BINARY = /home/totakura/gnunet/src/testbed/gnunet-service-test-barriers |
17 | 17 | ||
18 | [fs] | 18 | [fs] |
19 | AUTOSTART = NO | 19 | AUTOSTART = NO |