Thread: Get faulting address on SIGSEGV

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    7

    Get faulting address on SIGSEGV

    Hey all,

    I try to write a shared memory for a distributed computing system.

    In order to implement a kind of paging for this I want to invalidate the addresses of memory-pages that are currently not valid (using 'mprotect').
    Then, to page-in I want to catch SIGSEGV signals, and give them a special treatment if they occured because of any of the shared memory addresses.

    In order to do so I need to check if the faulting address is part of my shared memory.

    Is there some way to get the faulting address on a SIGSEGV signal?

    Thanks for any help!

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    You will need to use sigaction() to configure the signal handler instead of signal(). Ask again if the manual for sigaction() is not clear enough.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    Makes sense, thank you very much!

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    I encountered another problem.
    Is it possible to determine whether the fault occured because of an attempt to read or to write?
    I'd assume, that this can be done using siginfo_t, but can't figure out how.

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Doesn't look like you can tell, actually. Unless si_errno or si_code is telling that.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kruemelmonster View Post
    I encountered another problem.
    Is it possible to determine whether the fault occured because of an attempt to read or to write?
    I'd assume, that this can be done using siginfo_t, but can't figure out how.
    There is no direct way. But you could do this:

    1. open /proc/self/maps
    2. scan the region descriptors until you find the region which contains the faulting address
    3. check the map permissions for read/write/execute.

    Note that on many platforms (importantly, x86), not all combinations of permissions can be implemented at the hardware level. So you may not be able to distinguish, for instance, an illegal read vs. an illegal execute.

    But if both the 'r' and 'x' bits are set, then it's clear that the access was an illegal write. Make sense? (I'm assuming you're trying to implement COW, which is certainly possible with the available information)

    You could avoid scanning /proc/self/maps if you are keeping track internally of your memory maps.
    Last edited by brewbuck; 04-14-2009 at 11:31 AM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    Thank you very much for your replies!
    I solved it by requiring a write lock to be held in order to write, and assume that the access is a read if the lock is not held.

    However another problem appeared that I hope you guys can give me some help on as well.

    I installed a sigaction as suggested by brewbuck in the following way:

    Code:
    struct sigaction saSegf;
    struct sigaction oldAct;
    	
    saSegf.sa_sigaction = sighandler;
    sigemptyset(&saSegf.sa_mask);
    saSegf.sa_flags = SA_SIGINFO;
    	
    	
    if(0 > sigaction(SIGSEGV, &saSegf, NULL)); //&oldAct))
    	perror("Error SigAction SIGSEG");
    Unfortnuately the signal handler is not always called. Sometimes it gets called and sometimes the original handling is used.

    Is there something wrong with my way of setting up the sigaction?

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kruemelmonster View Post
    Unfortnuately the signal handler is not always called. Sometimes it gets called and sometimes the original handling is used.
    I don't see anything wrong with what you've got there. Can you describe the circumstance in more detail?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    Quote Originally Posted by brewbuck View Post
    I don't see anything wrong with what you've got there. Can you describe the circumstance in more detail?
    In the meantime I figured out, that the signal handler does not catch the signal if I run the program in gdb, but does catch it if I run it normally.

    However
    Code:
    if(0 > sigaction(SIGSEGV, &saSegf, NULL)); //&oldAct))
    	perror("Error SigAction SIGSEG");
    Always results in printing of "Error SigAction SIGSEG: Success", even when the signal handler gets successfully called afterwards.
    So I figure there is still a problem with installing the handler.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kruemelmonster View Post
    Code:
    if(0 > sigaction(SIGSEGV, &saSegf, NULL)); //&oldAct))
    	perror("Error SigAction SIGSEG");
    Always results in printing of "Error SigAction SIGSEG: Success", even when the signal handler gets successfully called afterwards.
    So I figure there is still a problem with installing the handler.
    I highlighted your problem in bold red.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  11. #11
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    Oh wow, thanks!
    Don't know how I could have missed that!

    Do you have any idea how to catch the signal using gdb?
    The handler gets installed successfully (checked with my updated if-statement )

  12. #12
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kruemelmonster View Post
    Oh wow, thanks!
    Don't know how I could have missed that!

    Do you have any idea how to catch the signal using gdb?
    The handler gets installed successfully (checked with my updated if-statement )
    gdb, like any other program which ptrace()'s another program, intercepts all signals for the process. It is gdb's decision whether to deliver the signal or to block it (as if the signal was never sent). Obviously gdb is deciding not to deliver the signal. There isn't much you can do.

    (Well, there is one thing. After gdb breaks on the SIGSEGV, you can continue execution by saying "signal 11" instead of "continue" -- this will deliver the original SIGSEGV. You just can't do it by default)
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  13. #13
    Registered User
    Join Date
    Mar 2009
    Posts
    7
    Quote Originally Posted by brewbuck View Post
    (Well, there is one thing. After gdb breaks on the SIGSEGV, you can continue execution by saying "signal 11" instead of "continue" -- this will deliver the original SIGSEGV. You just can't do it by default)
    That's good enough to be able to debug.
    Thanks a lot for your help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What does this do (Windows API)?
    By EVOEx in forum Windows Programming
    Replies: 4
    Last Post: 12-19-2008, 10:48 AM
  2. Writing array, to file
    By zootreeves in forum C Programming
    Replies: 9
    Last Post: 09-08-2007, 05:06 PM
  3. I thought pointers were pointers...
    By keira in forum C Programming
    Replies: 19
    Last Post: 08-15-2007, 11:48 PM
  4. DX - CreateDevice - D3DERR_INVALIDCALL
    By Tonto in forum Game Programming
    Replies: 3
    Last Post: 12-01-2006, 07:17 PM
  5. Im so lost at . .
    By hermit in forum C Programming
    Replies: 18
    Last Post: 05-15-2002, 01:26 AM