// Although in an unstable state, there is an initial implementation for error // handling. Roughly speaking: if a component has failed then it cannot complete // any current or future synchronous rounds anymore. Hence, apart from some edge // cases, any received message by a peer should cause a failure at that peer as // well. We may have a look at the various places where a component with respect // to a peer that is receiving its messages enum ErrorLocation { BeforeSync, DuringSyncBeforeFirstInteraction, DuringSyncBeforeSecondInteraction, DuringSyncAfterInteractions, AfterSync, } func error_location_to_string(ErrorLocation loc) -> string { if (let ErrorLocation::BeforeSync = loc) { return "before sync"; } else if (let ErrorLocation::DuringSyncBeforeFirstInteraction = loc) { return "during sync before first interaction"; } else if (let ErrorLocation::DuringSyncBeforeSecondInteraction = loc) { return "during sync before second interaction"; } else if (let ErrorLocation::DuringSyncAfterInteractions = loc) { return "during sync after interactions"; } else { return "after sync"; } } func crash() -> u8 { return {}[0]; // access index 1 of an empty array } comp sender_and_crasher(out value, ErrorLocation loc) { print("sender: will crash " @ error_location_to_string(loc)); if (loc == ErrorLocation::BeforeSync) { crash(); } sync { if (loc == ErrorLocation::DuringSyncBeforeFirstInteraction) { crash(); } print("sender: sending first value"); put(value, 0); if (loc == ErrorLocation::DuringSyncBeforeSecondInteraction) { crash(); } print("sender: sending second value"); put(value, 1); if (loc == ErrorLocation::DuringSyncAfterInteractions) { crash(); } } if (loc == ErrorLocation::AfterSync) { crash(); } } comp receiver(in value) { sync { auto a = get(value); auto b = get(value); } } // Note that when we run the example with the error location before sync, or // during sync, that the receiver always crashes. However the location where it // will crash is somewhat random! Due to the asynchronous nature of the runtime // a sender of messages will always just `put` the value onto the port and // continue execution. So even though the sender component might already be done // with its sync round, the receiver officially still has to receive its first // message. In any case, a neat error message should be displayed in the // console. // // Note especially, given the asynchronous nature of the runtime, that the // receiver should figure out when the peer component has crashed, but it can // still finish the current synchronous round. This might happen if the peer // component crashes *just* after the synchronous round. There may be a case // where the peer receives the information that the peer crashed *before* it // receives the information that the synchronous round has succeeded. comp main() { channel tx -> rx; new sender_and_crasher(tx, ErrorLocation::AfterSync); new receiver(rx); }