I call some C++ functions inside a signal handler and my program is terminated by segmentation fault. When I check with gdb, memcpy() function is where i get SIGSEGV. I would like to know if memcpy() is a reentrant function or not?
-
Look at where the signal handler gets the pointer values and length that it uses. `memcpy` is safe, but if you do something like `free(somestruct->data); somestruct->data = 0; somestruct->len = 0;` then of course the signal could occur in the middle of that. – Steve Jessop Mar 17 '11 at 10:47
5 Answers
In all but the most highly embedded platforms, it'll be reentrant. You mention SIGSEGV so I assume it's not one of those. In this case it's most likely memcpy() isn't the culprit: it's the caller's fault. If you ask memcpy() to copy bad pointers (or bad length) then it'll be the one which faults. You could easily do this:
memcpy(NULL, NULL, 123456789);
That'll cause a SIGSEGV and it'll tell you memcpy() caused it. Of course, it's not memcpy's fault - it's just doing what you told it. Your signal handler is calling it with something odd. A backtrace (in gdb or whatever tool you have) to the site of the caller should show what you called it with. Failing that, just printf the arguments you're passing to memcpy.

- 4,434
- 1
- 21
- 17
-
2Posix says that memcpy cannot be called from a signal handler. In practice, it may work. Most of the time, at least. But it's not at all guaranteed. – James Kanze Mar 17 '11 at 10:48
-
1@James: the way to check that, I suppose, would be to replace the call to `memcpy` with the obvious loop and see whether the segfault still occurs. If it goes away then `memcpy` wasn't async-signal-safe. If it doesn't, then either the problem lies elsewhere that the actual copy, or else it's something subtle to do with `char` access not being signal-atomic. – Steve Jessop Mar 17 '11 at 11:15
-
1@James That's extremely surprising. I can't find a reference to memcpy() not being signal-safe (even from opengroup). On some microcontroller/DSP architectures it's not reentrant due to having static locations for its local variables, but I can't imagine how you'd manage to make it unsafe on other architectures without trying really hard to make it so. Do you have a link? – John Ripley Mar 17 '11 at 17:33
-
1@James Actually, I see it now: "asynchronous safe" functions. But that's a list of POSIX functions which are system calls, not the basic C library functions. By that reading, even calling "strcmp" or "isdigit" would be unsafe. – John Ripley Mar 17 '11 at 17:38
-
4As you say, the list of async-signal-safe functions only mentions functions new to Posix, not standard C functions, and Posix says somewhere that any function not stated to be async-signal-safe is not required to be async-signal-safe. The C standard says you can't in general call library functions from signal handlers (7.1.4/4). So unless a standard explicitly says somewhere that you can call `memcpy`, all we're relying on is intuition about plausible implementations. We know that's not the bug, but AFAIK it isn't Posix that guarantees that. glibc might, though. – Steve Jessop Mar 17 '11 at 21:49
Some relevant information concerning (non)reentrant functions and signal handlers (as far as relevant to the GNU C library) can be found at http://www.gnu.org/s/libc/manual/html_node/Nonreentrancy.html#Nonreentrancy:
This part seems especially relevant to your question:
"Merely reading from a memory object is safe provided that you can deal with any of the values that might appear in the object at a time when the signal can be delivered. Keep in mind that assignment to some data types requires more than one instruction, which means that the handler could run “in the middle of” an assignment to the variable if its type is not atomic."
"Merely writing into a memory object is safe as long as a sudden change in the value, at any time when the handler might run, will not disturb anything."

- 12,333
- 2
- 41
- 48
I don't see why it could not be reentrant. I'm not sure, but i think its a lot based on the libraries you use.

- 3,750
- 3
- 27
- 49
Unless memcpy
is BADLY implemented, it is reentrant. It will only work with what you give it - the pointers and the length value. All parameters are passed by value, so once the function has been activated, these values will not change on its stack frame, regardless of signals and/or other threads.

- 4,839
- 3
- 28
- 51
I think that the problem is that you are using as parameters for the memcpy function a invalid (or deleted) pointer, please check your code carefully.
Regards.

- 1,170
- 2
- 10
- 23