Not necessarily.
If you are doing a whole series of transactions talking to say an external device and, if any of those transactions fail by getting stuck in a loop etc., you want to abandon the whole thing and start again, then this can be a use for "goto" as mentioned in post #2. You can set a timeout on the whole series. For example :
bool initiateSession() {
const uint32_t timeoutMs = 4000 ;
uint32_t startAtMs = millis() ;
while ( true ) {
if ( millis() - startAtMs > timeoutMs ) goto errorLabel ;
/*
do activity 1 here. when OK issue break
*/
}
while ( true ) {
if ( millis() - startAtMs > timeoutMs ) goto errorLabel ;
/*
do activity 2 here. when OK issue break
*/
}
return true ; // OK
errorLabel :
// handle error here. Issue error message etc.
return false ; // bad
}