segmentation fault in signal level - c

I have written a phone book and my person input like "name-number-type" and if the user give "_" or any other character that is not "-" as seperator the program will crash by seg. fault because i used strtok() to split input. Also if the user gives number that is not proper input like 1232414eree224, my program will crash again. So i just think that if i handle the seg. fault signal in os level may be i can fix this bug. I know that i can write a controller function but i am searching for a new way to deal with like that error. Is there any possible way to do this?

So i just think that if i handle the seg. fault signal in os level may
be i can fix this bug.
It does not seem like a good idea at all, a SIGSEGV handler ​​is not intended to ignore or try to fix the error, they are used to consistently exit your process, e.g. remove the used heap so that there are no memory leaks, to write in a log reporting the error ...
In addition, in the POSIX standard:
The behavior of a process is undefined after it returns normally from
a signal-catching function for a [XSI] SIGBUS, SIGFPE, SIGILL, or
SIGSEGV signal that was not generated by kill(), [RTS] sigqueue(), or
raise().

Related

Do multiple signals in C result in a segmentation fault?

When running my code, it crashes and says "Segmentation fault".
However, when I run through it in gdb, it crashes due to a SIGABRT error not a SIGSEGV.
Are there other signals that also "map" to a general Segmentation fault error on the terminal?
abort() sends the calling process the SIGABRT signal, this is how SIGABRT or Signal 6 is generated. Also, most "assert" implementations make use of SIGABRT in case of a failed assert.
abort() is usually called by library functions which detect an internal error or some seriously broken constraint. For example malloc() will call abort() if its internal structures are damaged by a heap overflow.
SIGSEGV or Signal 11, officially know as "segmentation fault", means that the program accessed a memory location that was not assigned. That's usually a bug in the program. So if you're writing your own program, that's the most likely cause. otherwise I do not see any other signal will create segmentation fault in a program.

Should segmentation fault handlers be written at all by a application programmer in C?

If someone is a operating system programmer or writing a system level library code, it makes sense to write a segmentation fault handler. Like, for example, OS programmer would write code send a signal SIGSEGV to that application process. OR a systems library programmer might handle that signal SIGSEGV and may undo the operations caused by the library code for creating segmentation Fault. But why would an application programmer in C need to write segmentation fault handler? If he writes an handler, he has already corrupted some parts of memory. Can you give an instance, for an application programmer to handle segmentation fault and continue execution of the program?
AFAIK, the segmentation handler can be written at the application level, to output some debugging information (like memory dump, value of registers and other application specific information) and then exit the application.
Pls note that, since the segmentation fault might have corrupted the memory, it may or may not get all the correct information to dump.
I am not aware of any situation, where the execution of the program can be continued after a segmentation fault. May be other esteemed users of SO will be able to throw some light on this.
Handling SIGSEGV, etc, may allow saving state and taking corrective actions. Mr 32 (and others) are correct and you can not simply restart the main line code. Instead you can longjmp()siglongjmp(); this allows a re-start of the main line. Also, you have to be very careful to call async safe functions only. This is very tricky. However some applications are,
Health/saftey - to ensure a catastrophic condition doesn't happen.
Financial - loss of transaction data that can result in a loss of money.
Control system - example titration software for chemists.
Diagnostics - Crash conditions maybe logged to improve future software. As per Jay
Calling exit() is probably not good and _exit() would be better. The difference being atexit() calls.
See also: Cert async safe, Glibc async-safe list, Similar question, longjmp() and signals not portable, async-safe
These vary from OS to OS. Any advice will be system dependent!
Additional Issues
Some libraries used by the program may catch SIGSEGV. Definitely version of the Empress Database hook it. You have to know what your libraries are using and chain to/from them.
Stack and heap (malloc,etc) can be corrupted, including the jump_buf so your error handling maybe especially paranoid.
There are many other alternate solutions, such as defer critical portions to another task that is much simpler.
longjmp() called from a signal is undefined according to the C99 standard, but it will work well on most systems. siglongjmp() can be used if you are more pedantic. It would be fine for diagnostic logging, but I wouldn't use it for the other uses listed (safety, etc). Notifying a watchdog task maybe more appropriate.
You can catch any signal except SIGKILL, SIGCONT and SIGSTOP. Thus you can catch SIGSEGV, but if you decide then not to exit, the behavior will be unpredictable.
library programmer might handle that signal SIGSEGV and may
undo the operations caused by the library code for creating segmentation
segmentation fault occurs means that threads or process will be died.
You can not undo the code caused the segmentation fault. Rather you can Re-start that component.
A segmentation fault is caused by the program writing to a portion of memory it is not supposed to. The application developer does not write code to handle this, they write code to avoid it. This is why you bound check when writing to memory.

Segmentation fault handling

I have an application which I use to catch any segmentation fault or ctrl-c.
Using the below code, I am able to catch the segmentation fault but the handler is being called again and again. How can I stop them.
For your information, I don't want to exit my application. I just can take care to free all the corrupted buffers.
Is it possible?
void SignalInit(void )
{
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = mysighandler;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
sigaction(SIGSEGV, &sigIntHandler, NULL);
}
and handler goes like this.
void mysighandler()
{
MyfreeBuffers(); /*related to my applciation*/
}
Here for Segmentation fault signal, handler is being called multiple times and as obvious MyfreeBuffers() gives me errors for freeing already freed memory. I just want to free only once but still dont want to exit application.
Please help.
The default action for things like SIGSEGV is to terminate your process but as you've installed a handler for it, it'll call your handler overriding the default behavior. But the problem is segfaulting instruction may be retried after your handler finishes and if you haven't taken measures to fix the first seg fault, the retried instruction will again fault and it goes on and on.
So first spot the instruction that resulted in SIGSEGV and try to fix it (you can call something like backtrace() in the handler and see for yourself what went wrong)
Also, the POSIX standard says that,
The behavior of a process is undefined after it returns normally from
a signal-catching function for a [XSI] SIGBUS, SIGFPE, SIGILL, or
SIGSEGV signal that was not generated by kill(), [RTS] sigqueue(),
or raise().
So, the ideal thing to do is to fix your segfault in the first place. Handler for segfault is not meant to bypass the underlying error condition
So the best suggestion would be- Don't catch the SIGSEGV. Let it dump core. Analyze the core. Fix the invalid memory reference and there you go!
I do not agree at all with the statement "Don't catch the SIGSEGV".
That's a pretty good pratice to deal with unexpected conditions. And that's much cleaner to cope with NULL pointers (as given by malloc failures) with signal mechanism associated to setjmp/longjmp, than to distribute error condition management all along your code.
Note however that if you use ''sigaction'' on SEGV, you must not forget to say SA_NODEFER in sa_flags - or find another way to deal with the fact SEGV will trigger your handler just once.
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
static void do_segv()
{
int *segv;
segv = 0; /* malloc(a_huge_amount); */
*segv = 1;
}
sigjmp_buf point;
static void handler(int sig, siginfo_t *dont_care, void *dont_care_either)
{
longjmp(point, 1);
}
int main()
{
struct sigaction sa;
memset(&sa, 0, sizeof(sigaction));
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_NODEFER;
sa.sa_sigaction = handler;
sigaction(SIGSEGV, &sa, NULL); /* ignore whether it works or not */
if (setjmp(point) == 0)
do_segv();
else
fprintf(stderr, "rather unexpected error\n");
return 0;
}
If the SIGSEGV fires again, the obvious conclusion is that the call to MyfreeBuffers(); has not fixed the underlying problem (and if that function really does only free() some allocated memory, I'm not sure why you would think it would).
Roughly, a SIGSEGV fires when an attempt is made to access an inaccessible memory address. If you are not going to exit the application, you need to either make that memory address accessible, or change the execution path with longjmp().
You shouldn't try to continue after SIG_SEGV. It basically means that the environment of your application is corrupted in some way. It could be that you have just dereferenced a null pointer, or it could be that some bug has caused your program to corrupt its stack or the heap or some pointer variable, you just don't know. The only safe thing to do is terminate the program.
It's perfectly legitimate to handle control-C. Lots of applications do it, but you have to be really careful exactly what you do in your signal handler. You can't call any function that's not re-entrant. So that means if your MyFreeBuffers() calls the stdlib free() function, you are probably screwed. If the user hits control-C while the program is in the middle of malloc() or free() and thus half way through manipulating the data structures they use to track heap allocations, you will almost certainly corrupt the heap if you call malloc() or free() in the signal handler.
About the only safe thing you can do in a signal handler is set a flag to say you caught the signal. Your app can then poll the flag at intervals to decide if it needs to perform some action.
Well you could set a state variable and only free memory if its not set. The signal handler will be called everytime, you can't control that AFAIK.
I can see at case for recovering from a SIG_SEGV, if your handling events in a loop and one of these events causes a Segmentation Violation then you would only want to skip over this event, continue processing the remaining events. In my eyes SIG_SEGV is similar to the NullPointerException in Java. Yes the state will be inconsistent and unknown after either of these, however in some cases you would like to handle the situation and carry on. For instance in Algo trading you would pause the execution of an order and allow a trader to manually take over, with out crashing the entire system and ruining all other orders.
Looks like at least under Linux using the trick with -fnon-call-exceptions option can be the solution. It will give an ability to convert the signal to general C++ exception and handle it by general way.
Look the linux3/gcc46: "-fnon-call-exceptions", which signals are trapping instructions? for example.

Segmentation Fault in presence of Signal Handler

I am getting segmentation fault despite having a signal handler for SIGSEGV. The first time data is written to protected memory, I can see that signal handler is called, but before the signal handler exits, segmentation fault appears.
What can be causing it? Isn't my SIGSEGV handler supposed to catch all the segmentation faults?
I could see where if the segmentation fault is related to the stack pointer accessing memory where it's not allowed by the OS, then you won't be able to make any calls with the current stack pointer for your process ... that includes calls to signal handlers. In other words the compiler-created prologue for your signal handler function has to setup an activation record on the stack ... if the stack pointer itself is invalid, then that won't be possible. One way this could happen is by overflowing a memory array that then writes-over the activation record for the currently executing function.
You can define another area of memory to be used as a stack for your signal handlers though sigaltstack(), and then setting the SA_ONSTACK option in sigaction() for the signal. This might be something you might want to try.
Finally, you could also run into issues if you're using non-async-safe functions or somehow are accessing pointers or memory that is outside the memory segment allotted to your process by the OS in your signal handler.
If your signal handler in turn provokes another signal that of course is not caught by your signal handler as you would then have a kind of infinite loop.

Question regarding multiple threads and segfaults

What happens when two threads of the same process running on different logical cpu hit a seg fault?
Default action is for the process to exit. If you handle the segfault, I suppose you could try to arrange for just the thread where it happened to terminate. However, since the only things which cause a segfault to occur naturally (as opposed to raise or kill) stem from undefined behavior, the program is in an indeterminate state and you can't rely on being able to recover anything.
Normal handling of a Segmentation Fault involves the termination of the process. That means that both of them are terminated.
I think the default action on all major OSes is to terminate the process. However, you could conceivably install (e.g using signal) an alternate handler that only terminated the thread. Of course, once you have a segmentation fault, behavior typically becomes undefined, and attempting to continue is risky.
Signals generated due to illegal execution are handled synchronously by the kernel. So even if both the threads generate seg fault at the same time, only one gets thru'.
The segfault handler is called for the process. If you don't do anything special, the OS will kill the process and reclaim its resources.

Resources