Dear All I'm going to start to use this two functions to perform a goto in case of a while 1 loop is added into some section of the code. into the main I've
if (setjmp (env) == 0) { blocked_loop =1; while (1); } else { blocked_loop = 0; //Continue to skip on while 1 infinite loop }
into an interrupt (a timer that is called each 2ms) i'll call
if (blocked_loop== 1) { blocked_loop = 0; longjmp (env, 1); /* return 1 to setjmp */ }
but it dosn't seems to works. Do you have any suggestion? Thanks in advance Best Regards Francesco Dodi
Yes. Consider what an interrupt actually is and then look at workable options for doing what you want to do. hint: setjmp and longjmp wont work between mainline code and an interrupt like that.
longjmp() is a bit of a hack. Or actually a rather big hack. And introduced because C did not have a good way to return many levels back in case of a serious error. C++ later introduced exceptions to unroll the stack all the way back to a suitable handler.
First off - longjmp() is a great way to write code that will leak resources since programs have no way to guarantee that the code will be able to undo any actions before the longjmp() skips back to some earlier call state.
And secondly - as noted, longjmp() is for a main execution thread to step back many steps. It is not for mixing interrupt and normal code. The interrupt is a very special processor state. And a longjmp() would not know if it needs to explicitly restore any processor state before returning to some position in the main code sequence.
A longjmp() will not clear any interrupt flags. It will not acknowledge any vectored interrupt controller. It will not switch any processor mode.
Thanks for the answer. So there is no way to use longjmp/setjmp for my purpose. Do you have any other ideas of how to force the return automatically from a function call in case of block (example while(1)?) of it?
coroutines...?
Tomorrow I'll try to find if it could be a solution www.chiark.greenend.org.uk/.../coroutines.html dunkels.com/.../examples.html but from a first overlook it I can't get how to return from a freezed function! (especially in C!)
Do you have any other ideas of how to force the return automatically from a function call in case of block (example while(1)?) of it?
Well, as the saying goes: "If that is the solution, I immediately demand a better problem!"
In other words, what you're trying to achieve there just makes no sense whatsoever. If you don't want endless loops in your software, don't put any into it ;-)
And how do you ever expect to be able to detect that a given loop is, in fact, endless? Note that one Alan Turing rigorously proved that very condition to be impossible to check, and he did so 78 years ago, back when "computer" was a person's job title.
Nor is it all that likely that blindly returning from the middle of some function would be helpful, or even possible. For starters: what will you then use for a return value of that function; what condition will its outputs, and the globals it modifies, be in? What makes you believe that the calling function can tolerate such nonsense?
The thing you appear to really be looking for is a watchdog circuit, preferrably one external to the CPU.
A watchdog is great for seriously misbehaving code.
And robust code should consider including timeouts for every loop - or at the very least loops that doesn't have hard count limits.
So a "wait_for_password()" should probably not blindly do while (1) { ... } until a password has been entered. It could be better to give up after x minutes without keyboard input and return with an explicit error code. Then have the caller clear the display and go back to wait for a user name.
The difference between "smart infinite loops" and the use of longjmp() is tht the smart loops have dedicated status codes to return back to the caller. And the caller will then be able to do whatever repair job that is deemed needed before the caller itself returns.
The C++ exceptions have a very complex design. All because of the need to let each individual call layer have a chance to capture the exception and perform suitable "repair" work before either considering the exception properly processed or throwing the exception further up the call chain.
Next thing is that C++ exceptions are still rather nice - they happen at specific places in the code. Places where the developer have explicitly implemented a "throw" statement. So C++ exceptions are synchronous events - synchronizing with the structure of the source code. longjmp() is also a synchronous construct where the jump can only start from locations where the developer have inserted jumps.
But interrupts are not synchronous. They are asynchronous and can happen at totally random positions in the source code. They can even happen between the individual processor instructions that the compiler have inserted to implement the functionality of an individual C source code statement. So a trival a = b + c can have the interrupt happen when the processor have just picked up the value of b. Or after the processor have retrieved the value of c. Or after the two values have been added together but still not been assigned to a. Or when the processor have picked up the address of a but before the result have been assigned to that address.
Think about how impossible it would be to write correct code if you could allow a longjmp() to happen from totally random positions in the sequence of machine code instructions.
Let's say your employer would want a mechanism to get you to quickly return to the work in case some crisis happens. Think about the difference of the employer being able to knock on the door or call you and you then synchronize what you are doing before leaving for work. Or if the employer instead had the power to press a button and teleport you back to work whatever you were doing. So your toilet visit could end up with you suddenly crouching with your pants at your ankles at the office. Do you really think that kind of asynchronous "return to base" would work well, or would it make your life into a living hell?
The watchdog will trig at an asynchronous position in the program execution path. But since the watchdog also implements a reset, it doesn't just interfere at a random position but it also restores the processor into a known state. So if that computer-controlled hydraulic lift suffers a watchdog reset, it can end up in a state where all power is cut and all vales are left in idle/off state. Then the software can try to pick up the pieces and figure out if it's safe to return the mechanics to a parking state or if the operator should be required to press a "all is safe - now return to the parked state". A watchdog that did just implemented an asynchronous jump without also introducing a normalization of state would give a hardware where the hydraulic pump would continue to run even if the control loop expected to measure when to stop has been forcefully terminated by that evil jump.
So in the end, it's best to write code that does not lock up but instead have alternative code paths already implemented to handle whatever timeout condition that could have hung a stupid infinite loop. And the second-best alternative is to have a watchdog force a reset to some form of safe state and then take it from there. An interrupt-activated longjmp() would just be a very big button with the text "let there be chaos". And chaos inside a program is never a good thing...