* Destroy a hook * * As hooks are always attached, this really destroys two hooks. * The one given, and the one attached to it. Disconnect the hooks * from each other first. We reconnect the peer hook to the 'dead' * hook so that it can still exist after we depart. We then * send the peer its own destroy message. This ensures that we only * interact with the peer's structures when it is loc
| 1161 | * on error detection and must be able to handle any such stage. |
| 1162 | */ |
| 1163 | void |
| 1164 | ng_destroy_hook(hook_p hook) |
| 1165 | { |
| 1166 | hook_p peer; |
| 1167 | node_p node; |
| 1168 | |
| 1169 | if (hook == &ng_deadhook) { /* better safe than sorry */ |
| 1170 | printf("ng_destroy_hook called on deadhook\n"); |
| 1171 | return; |
| 1172 | } |
| 1173 | |
| 1174 | /* |
| 1175 | * Protect divorce process with mutex, to avoid races on |
| 1176 | * simultaneous disconnect. |
| 1177 | */ |
| 1178 | TOPOLOGY_WLOCK(); |
| 1179 | |
| 1180 | hook->hk_flags |= HK_INVALID; |
| 1181 | |
| 1182 | peer = NG_HOOK_PEER(hook); |
| 1183 | node = NG_HOOK_NODE(hook); |
| 1184 | |
| 1185 | if (peer && (peer != &ng_deadhook)) { |
| 1186 | /* |
| 1187 | * Set the peer to point to ng_deadhook |
| 1188 | * from this moment on we are effectively independent it. |
| 1189 | * send it an rmhook message of its own. |
| 1190 | */ |
| 1191 | peer->hk_peer = &ng_deadhook; /* They no longer know us */ |
| 1192 | hook->hk_peer = &ng_deadhook; /* Nor us, them */ |
| 1193 | if (NG_HOOK_NODE(peer) == &ng_deadnode) { |
| 1194 | /* |
| 1195 | * If it's already divorced from a node, |
| 1196 | * just free it. |
| 1197 | */ |
| 1198 | TOPOLOGY_WUNLOCK(); |
| 1199 | } else { |
| 1200 | TOPOLOGY_WUNLOCK(); |
| 1201 | ng_rmhook_self(peer); /* Send it a surprise */ |
| 1202 | } |
| 1203 | NG_HOOK_UNREF(peer); /* account for peer link */ |
| 1204 | NG_HOOK_UNREF(hook); /* account for peer link */ |
| 1205 | } else |
| 1206 | TOPOLOGY_WUNLOCK(); |
| 1207 | |
| 1208 | TOPOLOGY_NOTOWNED(); |
| 1209 | |
| 1210 | /* |
| 1211 | * Remove the hook from the node's list to avoid possible recursion |
| 1212 | * in case the disconnection results in node shutdown. |
| 1213 | */ |
| 1214 | if (node == &ng_deadnode) { /* happens if called from ng_con_nodes() */ |
| 1215 | return; |
| 1216 | } |
| 1217 | LIST_REMOVE(hook, hk_hooks); |
| 1218 | node->nd_numhooks--; |
| 1219 | if (node->nd_type->disconnect) { |
| 1220 | /* |
no test coverage detected