I'm using the couple sigsetjmp and singlongjmp with SIGALARM for interrupting a system call, which is illustrated in the following code
//data of Alarm_interrupter
void (TClass::*fpt)(const char*); // pointer to member function
TClass* pt2Object; // pointer to object
===================================================
//for timeout processing
static sigjmp_buf jmpbuf;
static void recvfrom_alarm(int) {
siglongjmp(jmpbuf, 1);
}
======================================================
void Alarm_interrupter::start_timeout() {
signal(SIGALRM, recvfrom_alarm);
alarm(timeout);
(*pt2Object.*fpt)("timeouted before sigsetjmp"); //this call works OK
if (sigsetjmp(jmpbuf,1) != 0) {
//at this point, pt2Object is still OK,
//but fpt seems to point to nothign.
(*pt2Object.*fpt)("timeouted after sigsetjmp");
}
return;
}
==============================================================
Before sigsetjmp returnn 1, the call using object and the method pointer: *pt2Object.*fpt("timeouted before sigsetjmp") is OK, but after sigsetjmp return 1, this call failed.
After examining the state of variables, I noticed that the object pointer "pt2Object" is still Ok, but the method pointer "fpt" seems to different.
I think that one possible reasons for this is that sigsetjmp cannot restore the whole earlier environment, which includes the method pointer "fpt".
Could you guys help me fix this problem. Thanks so much!
As Potatoswatter points out, using the alarm to delay the longjmp is too clever to rely upon. You have to call 'sigsetjmp' first. It has to happen before you try to return there.
The only way sigsetjmp or setjmp will work is following this pseudocode.
if (sigsetjmp(...) != 0) {
// Error handling code
}
// code that might call siglongjmp to bail out to Error handling code
You see, it has to be executed once to perform the save of the context. This initializes the jmpbuf. If you call longjmp without having called setjmp earlier in the execution, the behavior cannot be predicted.
Also, longjmp will tend to obliterate any local variables you might try to use.
int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // could print 2, 3 or even "potato". Local vars get trashed.
}
// code that might call siglongjmp to bail out to Error handling code
So you really want to do everything interesting after the *setjmp.
int var = 3;
if (sigsetjmp(...) != 0) {
// Error handling code
var = 2;
printf("%d", var); // now you know it's 2
}
// code that might call siglongjmp to bail out to Error handling code
For any hope of it surviving across the *longjmp, it needs to be marked volatile.
volatile int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code
And even this may not be enough. It may need to be something called a sigatomic_t or something similar. But try not to need crazy stuff like that.
int var = 3;
memcpy(var, (int *){2}); //memcpy is pretty reliable (C99ism: immediate pointer))
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code
Related
I am writing a c-style function:
enum {
EFUNC1,
EFUNC2,
}
int func0() {
int err = 0;
if((err=func1())!=0) {
// return err or return EFUNC1
}
if((err=func2())!=0) {
// return err or return EFUNC2
}
return 0;
}
func1 and func2 are c functions and they have their own error codes. What should I do when func1 or func2 return an error? I figure out some ways:
Design my error codes. The number of error codes is the sum of func1's and func2's. When the call stack is deep, the number of error codes becomes large.
Simply return the result of func1 or func2. There is no way to know which function fails since their error codes may overlap.
Design my error codes and the number of the codes is equal to the number of functions. The caller just know which function return error, but he don't know the further reason.
Throw an exception wrapping the failed function name and its error code.
What's the best practice?
The previous code example is ambiguous. I modified it.
Why expose the complexity of func0() to the caller? Usually the caller is not interested in what happens in the body of the function, he just wants the job to be done.
func0() should notify the user on why it failed to complete its goal (to terminate without errors). They are many ways to do that. One example could be this:
// On success: Return 0
// On error: Return -1
int func0() {
if(func1() == -1) {
printf("Error in func0: func1 returned error code -1");
return -1;
}
if(func2() == -2) {
printf("Error in func0: func1 returned error code -2");
return -1;
}
return 0;
}
Note that here we don't allow func2() to be executed if func1() fails, since that might be dangerous.
For instance, if func1() is suppose to allocate space for an array that func2() is going to use, then let's say that func1() fails (because malloc() failed). func2() should not be called, since func1() failed in that case, because the array that func2() expects to be ready for use, is not available at runtime.
Echoing tobi303's comment, the logic behind error codes is as follows:
If a routine (func0) will fail when an error occurs in a certain subroutine (func1), the routine should stop immediately on error and report back to the caller.
To do otherwise makes no sense. For example, if func0 is to make coffee, func1 is to get some beans and func2 is to brew, then without the beans, you are just brewing air. Telling someone you can't brew air isn't awfully helpful.
If a routine can gracefully handle an error in its subroutine, then its not an error at all for the caller of the routine. In this case, no error should be returned.
So the structure of your program for the first case should be simply
int func0()
{
if(int err = func1())
return err;
if(int err = func2())
return err;
return 0;
}
And the second case
int func0()
{
if(int err = func1())
handle(err);
if(int err = func2())
return err;
return 0;
}
Dear Stackoverflow Users,
I have an interesting question and I wish to hear your opinions out, also please correct me at any part.
In a normal PC the memory adresses splits into 3 parts, stack, heap, globals, (lets forget peripherials now), so if I go ahead and make a bad recursive function which fills the stack with calls, the OS will send a message of stackoverflow, also if I make an infinite loop with a new keyword in it, it'll fill the heap with junk data, and get something like segfault, but what if I make such mistakes in an arduino project?
try / catch blocks are out of the game, so I tried to make my own realization of error handling in loop(), abusing the stupidity of the preprocessor:
#define THROW(errval) \
ERROR = errval; \
loop()
#define TRY \
if(ERROR == 0)
#define CATCH(err) \
else if(err == ERROR)
#define FINALLY \
if(ERROR != 0)
#define OUT_OF_MEMORY 1
int ERROR = 0;
void random_routine() {
if(/*something goes wrong*/) {
THROW(OUT_OF_MEMORY);
}
}
void start() { Serial.begin(9600); }
void loop() {
TRY {
random_routine();
} CATCH(OUT_OF_MEMORY) {
Serial.println("out of memory");
} FINALLY {
while(true);
}
}
Now you might not see the trick here instantly so this is what you get after the preprocessing:
void random_routine() {
if(/*something goes wrong*/) {
ERROR = 1;
//this call is the body of my exception handling solution
//and the question is about this as well
loop();
}
}
void start() { Serial.begin(9600); }
void loop() {
///TRY-s macro result
if(ERROR == 0) {
random_routine();
///chainable CATCH blocks
} else if(ERROR == 1) {
Serial.println("Out of memory");
}
///FINALLY block
if(ERROR != 0) {
while(true);
}
}
So my question is, what if the memory gets full for some reason, will a function call be able to get executed? Because the THROW macro will always call loop() that way my idea to 'escape' from the current context and get into an infinite loop
Sorry for my bad english
So, if you want to exit a function and get back to where you came from, you should leave the function, not call the original function! Either by returning from the function, or use setjmp and longjmp.
And in all cases, you also need to worry about "how does data get cleaned up". In other words, if you allocate memory, then you need to free it before leaving the function, of you have opened a file, you need to close it, etc.
These sort of things is where the RAII principle comes in very handy, but it assumes you leave the function under the knowledge of the compiler, and not that you just jump back to your main loop without cleaning up. It will sooner or later cause problems.
Note also that the behaviour with stack overflow is UNDEFINED BEHAVIOUR - it MAY crash the program immediately, or it may cause the heap to be overwitten, format your harddrive/SD Card, or it may cause daemons to fly out of your nose. Or anything else you can possibly imagine and then some. It is undefined, you can't rely on it doing anything in particular - just that "you're not supposed to do that".
I'm going crazy with this piece of code. I have a thread that calls regularly to this method:
void deliverMsgQ() {
if(delMsgQ_mutex.try_lock() == false){
return;
}
while(delMsgQ.empty() == false){
std::vector<unsigned char> v = delMsgQ.front();
delMsgQ.pop();
}
delMsgQ_mutex.unlock();
}
void processInMsgQ() {
if(inMsgQ_mutex.try_lock()){
if(delMsgQ_mutex.try_lock() == false){
inMsgQ_mutex.unlock();
}
}else{
return;
}
while(!inMsgQ.empty()){
std::vector<unsigned char> msg;
inMsgQ.front()->getData(msg);
std::cout << "Adding to del-msg-q: " << msg.size() << std::endl;
delMsgQ.push(msg);
delete inMsgQ.front();
inMsgQ.pop();
}
inMsgQ_mutex.unlock();
delMsgQ_mutex.unlock();
}
I have another thread pushing vector to the queue also periodically. These two threads are the only ones that touch the queue delMsgQ.
My problems comes in the first function posted, for some reason delMsgQ.empty() at some point returns false even though it has no vectors in it, and therefore I end up calling pop twice. This causes the size function to become a huge unrealistic number and then the program goes into segmentation fault. I can fix this if I add an additional check right before calling pop, but I would expect that checking once would be enough since I'm also using mutexes. So the other alternative would be that maybe I'm using mutexes wrong, but as far as I know this is the proper way to use them in this case. So I was hoping that maybe someone smarter could let me know if there is something I'm missing? I hope this code is enough, I can provide with more code if necessary although no other function touch the queue that is failing.
best regards
Your code in processInMsgQ() (spaced out a little better but functionally identical) is problematic:
if (inMsgQ_mutex.try_lock()) {
if (delMsgQ_mutex.try_lock() == false) {
// Point A
inMsgQ_mutex.unlock();
// Point B.
}
} else {
return;
}
// Point C.
In the case where it locks inMsgQ_mutex but fails to lock delMsgQ_mutex (point A), it will free the first and then drop through to point C. This means you will be doing stuff that requires both locks without either lock, and that's unlikely to end well :-)
As a solution, you could put another return at point B but the following code is probably cleaner:
// If either lock fails, return ensuring that neither is locked.
if (! inMsgQ_mutex.try_lock()) {
return;
}
if (! delMsgQ_mutex.try_lock() {
inMsgQ_mutex.unlock();
return;
}
// At this point, you have both locks. Carry on ...
You'll notice I've also changed your some_boolean == false to the more usual ! some_boolean. That's the more accepted way of doing that particular check.
What my function does is iterate through an array of bools and upon finding an element set to false, it is set to true. The function is a method from my memory manager singleton class which returns a pointer to memory. I'm getting an error where my iterator appears to loop through and ends up starting at the beginning, which I believe to because multiple threads are calling the function.
void* CNetworkMemoryManager::GetMemory()
{
WaitForSingleObject(hMutexCounter, INFINITE);
if(mCounter >= NetConsts::kNumMemorySlots)
{
mCounter = 0;
}
unsigned int tempCounter = mCounter;
unsigned int start = tempCounter;
while(mUsedSlots[tempCounter])
{
tempCounter++;
if(tempCounter >= NetConsts::kNumMemorySlots)
{
tempCounter = 0;
}
//looped all the way around
if(tempCounter == start)
{
assert(false);
return NULL;
}
}
//return pointer to free space and increment
mCounter = tempCounter + 1;
ReleaseMutex(hMutexCounter);
mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];
}
My error is the assert that goes off in the loop. My question is how do I fix the function and is the error caused by multithreading?
Edit: added a mutex to guard the mCounter variable. No change. Error still occurs.
I can't say if the error is caused by multi threading or not but I can say your code is not thread safe.
You free the lock with
ReleaseMutex(hMutexCounter);
and then access tempCounter and mUsedSlots:
mUsedSlots[tempCounter] = true;
return mPointers[tempCounter];
neither of which are const. This is a data race because you have not correctly serialized access to these variables.
Change this to:
mUsedSlots[tempCounter] = true;
const unsigned int retVal = mPointers[tempCounter];
ReleaseMutex(hMutexCounter);
return retVal;
Then at least your code is thread safe, whether this solves your problem I can't say, try it out. On machines with multiple cores very weird things to happen as a result of data races.
As general best practice I would suggest looking at some C++11 synchronization features like std::mutex and std::lock_guard, this would have saved you from your self because std::lock_guard releases that lock automatically so you can't forget and, as in this case, you can't do it too soon inadvertently. This would also make your code more portable. If you don't have C++11 yet use the boost equivalents.
Why isn't setjmp saving the stack?
Consider the following code:
#include <iostream>
jmp_buf Buf;
jmp_buf Buf2;
void MyFunction()
{
for(int i = 0; i < 5; i++)
{
std::cout << i << std::endl;
if(!setjmp(Buf))
longjmp(Buf2, 1);
}
}
int main (int argc, const char * argv[])
{
while(true)
{
if(!setjmp(Buf2))
{
MyFunction();
break;
}
longjmp(Buf, 1);
}
return 0;
}
What I except is that the code will jump back and forth from main to the function and back printing increasing number every time.
What actually happens is that it prints 0 and then 1 infinite number of times. it is as if when it jumps back into the function the stack is reset to defaults. why is it doing it? is there any way I can make it save the stack too?
I know setjmp and longjmp are even worse than goto when it comes to coding style and readable code, but I am experimenting right now, and this code will probably never see the light of a usable application.
Because unfortunately thats not how setjmp works. setjmp copies the current instruction pointer and register set into the jump buffer but it does not copy the stack (obviously be cause the stack is huge). It looks like you want to use some kind of coroutine based techniques. If you want to do this yourself checkout the ucontext procedured (ucontext.h) http://compute.cnr.berkeley.edu/cgi-bin/man-cgi?ucontext.h+3 they will help you to allocate and manage additionaly thread stacks.
or you could use something like Russ Cox's libtask (http://swtch.com/libtask/) which will help do this for you. Or if you want to do it yourself you should take a look at the libtask code (also available through that link). It's pretty easy to read so its a good resource.