Re: memmove crash



Richard Cooper wrote:
On Fri, 16 Sep 2005 00:49:32 -0400, T.M. Sommers <tms@xxxxxx> wrote:

Why not reduce the code to the bare minimum necessary to show the problem, and post it?

That was the first thing I tried to do, but my test program didn't reproduce the problem.

Which usually means that the problem is in the code that was removed.

Anyway, a simple strace reveals the part of the problem:

--- SIGSEGV (Segmentation fault) @ 0 (0) ---
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

Two consecuative segmentation faults without a re-registration of the signal handler.

Which is what I suggested. Some Linux kernels and libcs follow the old signal behavior, in which the handler is reset to SIG_DLF when a signal is caught; other versions follow the BSD model, and don't. So the first step is to determine which behavior your system follows.


Here's the code:

#include <asm/unistd.h>
#include <stdio.h>
#include <string.h>

void handler(int);

int main(void) {

  /* Register a signal handler directly with the kernel. */
  int result;
  asm volatile (
    "int $0x80"
    :"=a" (result)
    :"a" (__NR_signal), "b"  (11), "c"  (handler)
  );
  printf("Result of kernel call: %d\n", result);

signal() does not return an int; it returns a sighandler_t in Linux.

  /* Allocate some memory... */
  char *memory1; memory1 = (char*) malloc(4096);
  char *memory2; memory2 = (char*) malloc(4096);

Don't cast the value returned by malloc(), and be sure to include stdlib.h. And, of course, you should test the return value from malloc().


If you care about portability, you should probably not use the C99 feature that allows intermixing of data definitions and code, as that is not yet implemented everywhere. This would not compile on my (old) Linux system.

  printf("Malloc's pointer: %u\n", memory1);
  printf("Malloc's pointer: %u\n", memory2);

Better to use %p to print a pointer value.

  /* Do a perfectly safe memmove(). */
  memmove(memory1, memory2, 4096);

  /* Cause a segmentation fault. */
  volatile int *crash = NULL; *crash++;

Why not use raise()?

  /* Cause a different segmentation fault. */
  memmove(memory2, memory1, -4096);

This, I think, is the real problem. My understanding is that this invokes undefined behavior. I see nothing in the C or POSIX standards that requires a SIGSEGV to be raised in the case of undefined behavior. The system can do anything at all. FreeBSD seems to get into an infinite loop, or at least a loop that goes on beyond my patience. Solaris does raise a signal.


  /* Keep GCC from complaining... */
  return 0;

You put in a return not to keep gcc happy, but because main is supposed to return an int, so you should return one.


};

void handler(int signum) {
  printf("Recieved Signal #%d\n", signum);

This is a potential problem. It is not safe to call printf() in a signal handler. write() is okay, though.


  _exit(1);
};

But the solution to your problem is easy: use atexit().

--
Thomas M. Sommers -- tms@xxxxxx -- AB2SB

.



Relevant Pages

  • Re: Design Questions on Termination
    ... Tw has an signal handler handler that is just use to awake Tw if if is ... set Tw's terminate flag ...
    (comp.programming.threads)
  • Re: signal catching not work
    ... you did not tell us what you were expecting. ... static int i=0; ... Undefined behavior #2, executing longjmp inside a signal handler. ...
    (comp.lang.c.moderated)
  • Re: memmove crash
    ... Two consecuative segmentation faults without a re-registration of the signal handler. ... standard library functions, do not get invalid arguments, thus invoking undefined behavior. ... tables that tell malloc what/how to allocate memory, and then the fprintf function allocates a small chunk of memory for a buffer, gets a bad pointer returned from malloc, and proceeds to use it, causing another segmentation fault. ... So I've learned that void pointers can't actually be used for anything without GCC having a fit, and so I've learned to cast all pointers to the data type that I'm going to use them for. ...
    (alt.lang.asm)
  • Re: va_arg and short
    ... > Chapter and verse, please. ... and returning from the signal handler might itself cause ... as a practical matter there's little difference between ... this and undefined behavior, at least for programs intended to be ...
    (comp.lang.c)
  • Re: <signal.h> - question about signals
    ... >> void sighandler(int signum) ... >dangerous calling printf ni a signal handler, ... Then write the loop in main to check this flag and do "we've been ...
    (comp.lang.c)