-1

I have to use c++ classes which is not properly written - there is no information if one function in loop is executed properly or not. If it is not, I receive segmentation fault and I'm loosing everything what was calculated. I would like to convert SIGSEGV signal to break loop. Is there any possibility? Using signal handlers from #include <csignal> doesn't help.

Cœur
  • 37,241
  • 25
  • 195
  • 267
JSB
  • 3
  • 4
  • When the exception is raised you do not get a dump as a popup to debug the code? – NathanOliver Apr 29 '16 at 11:57
  • as far as I am concerned, there no straight way to do it. If you add and handler, it'll go to infinite loop, anyway... – Sourav Ghosh Apr 29 '16 at 11:58
  • 6
    If something is segfaulting, there's a very good chance that it's also scribbling over other memory. Continuing to run after a segfault seems like a really dangerous thing to do, even if you find a way to make it happen. – Gareth McCaughan Apr 29 '16 at 11:59
  • I get dump and I know what is cause of fault but I can not debug someones class due to copyright etc. I have to live with this fault. I just want to break loop, and safely end program. – JSB Apr 29 '16 at 12:00
  • 4
    If you really truly have to use someone else's code that's so badly written it segfaults, consider writing a *separate program* to do that, communicating with yours via pipes or files or shared memory or something. Then if it fails the damage it can do to the rest of your program is limited. – Gareth McCaughan Apr 29 '16 at 12:00
  • 1
    `siglongjmp()` out of the signal-handler to a previously set `sigsetjmp()`? – EOF Apr 29 '16 at 12:01
  • Another option, if your plan was to clean up and exit as soon as the segfault happens, would be to save as much as necessary of your program's state to a file before calling into the dodgy third-party code. Then if your program crashes you haven't lost everything. – Gareth McCaughan Apr 29 '16 at 12:03
  • http://stackoverflow.com/questions/2350489/how-to-catch-segmentation-fault-in-linux – smali Apr 29 '16 at 12:05
  • 1
    @JSB Quit and find a better job. Being forced to use a library that crashes without the ability to fix it is unacceptable. When the desk in your office catches fire once a week, the correct action is not to find an umbrella for the sprinklers. Same goes for code. Code is your work environment. – Art Apr 29 '16 at 12:08
  • 1
    A segment violation is either a signal of defective OS or hardware or your application invoking undefined behaviour. Concentration on the latter, you can avoid this completely by writting correct code (at least in the incriminated loop). Just get your code correct and there is no need to try "catching" UB. To state it very clear: If you get segfaults, your code is broken! – too honest for this site Apr 29 '16 at 12:10
  • 1
    @Olaf: All good advice, but OP didn't write that code. It's code of a 3rd party library OP has no access to. My suggestion: Get the vendor of that 3rd party library to fix his sh** and if that doesn't happen, drop that dependency. – datenwolf Apr 29 '16 at 12:14
  • 1
    @datenwolf: The recommendation is the same. Just read the "you" as plural with a "delegate" (aka "kick a**s") option. – too honest for this site Apr 29 '16 at 12:15
  • @Olaf: I fully agree. See my answer on the two kinds of segfaults one may experience. – datenwolf Apr 29 '16 at 12:33
  • @Art it is very difficult to quit university. Expanding your analogy, I need fire extinguisher to save papers from desk and archive them. – JSB Apr 29 '16 at 12:39
  • @JSB: I realize the tough spot you are in. As already told, using a separate process is the only half-sane way to deal with this. You don't have to write a separate program for this. You can fork the main program just fine. I wrote you a little example program that adds a small proxy/helper function that does the fork and implements a channel to transfer back the data. https://gist.github.com/datenwolf/faf828e9facb53929482a94220441a15 – datenwolf Apr 29 '16 at 15:08
  • @JSB: The image is only complete if the papers are already buring. And as every fireman can tell, there is always collateral damage due to the water or foam. – too honest for this site Apr 29 '16 at 17:15

1 Answers1

0

A segmentation fault may happen in two ways:

  • uncontrolled segfaults where a process is accessing addresses for which this access is not well defined.

@JSB this is the case you're dealing with and there's little you can do about it, other then getting the offending code fixed.

When an uncontrolled segfault happens, which is the case for buggy code in 99.999% of all cases the only reasonable thing to do is cover your losses (you may write to already opened files from a SIGSEGV handler) and terminate the process.


@JSB the following does not apply to you! This is just for completenes!

  • "controlled" segfaults where a process accesses addresses which are allocated by the process, but read/write/execute access is disabled.

A controlled segfault may be induced in the following way

size_t const sz_p = pagesize;
char *p = mmap(NULL, sz_p, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
strcpy(p, "sigsegv");

So why is this a controlled segfault? Because you can actually react to it in a sensible way. In the SIGSEGV handler you can set the memory protection of the pages which access caused the segfault to allow the access

void sigsegv_handler(int, siginfo_t *info, void *)
{
    if( ((char*)info->si_addr - p) < sz_p
     && ((char*)info->si_addr - p) >= 0 ) {
        mprotect(p, sz_p, PROT_READ | PROT_WRITE);
    }
}

It is important to understand that this kind of SIGSEGV handler is well behaved and defined only if the segfault was caused by access to an actually allocated memory objects and if the signal handler action only sets memory protection flags on memory objects owned by the process. You can't use it to make broken code magically work!

So why would one actually do this? One example would be client side implementation of APIs that allow network distribution and also allow to map objects into memory, like OpenGL, which has the API functions glMapBuffer / glUnmapBuffer. To avoid unneccesary round trips and transfer you'd want to transfer only those parts of the buffer actually read from and/or modified. For this you have to somehow detect which pages a program touches. Some OSs (like Windows) have a dedicated API for this, but in *nix-es you have to work with mmap + mprotect + SIGSEGV handler tricks to implement this.

datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • So I understand that I am lost and I have to write backup files every correct iteration. – JSB Apr 29 '16 at 12:42
  • @JSB: No, you have the option to get that rubbish code fixed or get rid of it and get your money back. Not sure how your company handles such problems, but I have the strict policy not to accept broken code I pay for. I'm very much for being tolerant, but not when it comes to quality/stability in production code. – too honest for this site Apr 29 '16 at 13:06
  • @JSB: Yes, you're pretty much SOL. As a workaround you could try forking the inner loop into a separate process, adding the trouble of somehow getting the data back (shared memory? writing it through a anonymous pipe?). Using any kind of workaround to implement this will be a kludge and come with a very noticeable performance hit. – datenwolf Apr 29 '16 at 14:09
  • @JSB: I realize the tough spot you are in. As already told, using a separate process is the only half-sane way to deal with this. You don't have to write a separate program for this. You can fork the main program just fine. I wrote you a little example program that adds a small proxy/helper function that does the fork and implements a channel to transfer back the data. http://gist.github.com/datenwolf/faf828e9facb53929482a94220441a15 – datenwolf Apr 29 '16 at 15:09
  • @JSB: Just to emphasis: It must be a process, i.e. separate memory spaces, etc., not just a thread! (@ datenwolf: I had a similar problem with a not-so-newbie (at least so he said) not so long ago, who confused threads and processes, messing up parts of a project until we noticed). – too honest for this site Apr 29 '16 at 17:12