I have some code that uses libgmp. At some point the user may request a factorial of a very large number. Unfortunately, this results in libgmp raising an abort signal.
For example the following code:
#include <cmath>
#include <gmp.h>
#include <iostream>
int main() {
mpz_t result;
mpz_init(result);
mpz_fac_ui(result, 20922789888000);
std::cout << mpz_get_si(result) << std::endl;
}
Results in:
$ ./test
gmp: overflow in mpz type
Aborted
Apparently, the number produced is REALLY big. Is there anyway to handle the error more gracefully than an abort. This is a GUI based application and it aborting is pretty much the least desirable way to handle this sort of issue.
It would appear that you are out of luck, based on the code in mpz/realloc.c and mpz/realloc2.c. If too much memory was requested, it just does this:
if (UNLIKELY (new_alloc > INT_MAX))
{
fprintf (stderr, "gmp: overflow in mpz type\n");
abort ();
}
The best way to handle these errors gracefully in your application is probably to fork off a helper process to perform the GMP calculations. If the helper process is killed by SIGABRT, your parent process can detect that and report an error to the user.
(The below is my original answer, which has "undefined results" according to the GMP documentation - it is left here for completeness).
You can catch the error if you install a signal handler for SIGABRT that uses longjmp():
jmp_buf abort_jb;
void abort_handler(int x)
{
longjmp(abort_jb, 1);
}
int dofac(unsigned long n)
{
signal(SIGABRT, abort_handler);
if (setjmp(abort_jb))
goto error;
mpz_t result;
mpz_init(result);
mpz_fac_ui(result, 20922789888000);
std::cout << mpz_get_si(result) << std::endl;
signal(SIGABRT, SIG_DFL);
return 0;
error:
signal(SIGABRT, SIG_DFL);
std::cerr << "Caught SIGABRT from GMP.\n";
return 1;
}
Overwrite abort() with LD_PRELOAD.
What is the LD_PRELOAD trick?
Edit: To make the answer more self-contained, I copy the text of that answer here:
If you set LD_PRELOAD to the path of a shared object, that file will be loaded before any other library (including the C runtime, libc.so). So to run ls with a your special malloc() implementation, do this:
$ LD_PRELOAD=/path/to/my/malloc.so /bin/ls
Credits to JesperE.
Related
I have a class with a user-defined destructor. If the class was instantiated initially, and then SIGINT is issued (using CTRL+C in unix) while the program is running, will the destructor be called? What is the behaviour for SIGSTP (CTRL + Z in unix)?
No, by default, most signals cause an immediate, abnormal exit of your program.
However, you can easily change the default behavior for most signals.
This code shows how to make a signal exit your program normally, including calling all the usual destructors:
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>
std::atomic<bool> quit(false); // signal flag
void got_signal(int)
{
// Signal handler function.
// Set the flag and return.
// Never do real work inside this function.
// See also: man 7 signal-safety
quit.store(true);
}
class Foo
{
public:
~Foo() { std::cout << "destructor\n"; }
};
int main(void)
{
struct sigaction sa;
memset( &sa, 0, sizeof(sa) );
sa.sa_handler = got_signal;
sigfillset(&sa.sa_mask);
sigaction(SIGINT,&sa,NULL);
Foo foo; // needs destruction before exit
while (true)
{
// do real work here...
sleep(1);
if( quit.load() ) break; // exit normally after SIGINT
}
return 0;
}
If you run this program and press control-C, you should see the word "destructor" printed.
Be aware that your signal handler function (got_signal) should rarely do any work, other than setting a flag and returning quietly, unless you really know what you are doing. See also: https://man7.org/linux/man-pages/man7/signal-safety.7.html
Most signals are catchable as shown above, but not SIGKILL, you have no control over it because SIGKILL is a last-ditch method for killing a runaway process, and not SIGSTOP which allows a user to freeze a process cold. Note that you can catch SIGTSTP (control-Z) if desired, but you don't need to if your only interest in signals is destructor behavior, because eventually after a control-Z the process will be woken up, will continue running, and will exit normally with all the destructors in effect.
If you do not handle these signals yourself, then, no, the destructors are not called. However, the operating system will reclaim any resources your program used when it terminates.
If you wish to handle signals yourself, then consider checking out the sigaction standard library function.
Let's try it:
#include <stdio.h>
#include <unistd.h>
class Foo {
public:
Foo() {};
~Foo() { printf("Yay!\n"); }
} bar;
int main(int argc, char **argv) {
sleep(5);
}
And then:
$ g++ -o test ./test.cc
$ ./test
^C
$ ./test
Yay!
So I'm afraid not, you'll have to catch it.
As for SIGSTOP, it cannot be caught, and pauses the process until a SIGCONT is sent.
Background: Downloaded google-coredumper-1.2.1.tar.gz from code.google.com. built the code and make install. Added library and function call to my application and execute. No core file, Logs state Operation not permitted. So I created a simple example and stepped through it and found that the library believes that the executable is already being traced. Any ideas?
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include "crashtest.h"
#include <google/coredumper.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
FILE * backtrace_file = NULL;
#define SIZE 100
void CREATE_COREDUMP()
{
printf("NOTICE, Creating a core dump for debugging\n");
char extension[64];
time_t t = time((time_t*)NULL);
tm * theTime = localtime(&t);
snprintf( extension,
sizeof(extension) - 1,
"core.crashtest_02d_%02d_%02d_%02d", (theTime->tm_mday),
(theTime->tm_hour),
(theTime->tm_min) ,
(theTime->tm_sec) );
if (WriteCoreDump(extension) != 0) {
std::string errmsg(extension);
errmsg.append(" : ");
errmsg.append(strerror(errno));
printf("WARNING, Failed to create coredump: %s\n", errmsg.c_str() );
}
}
static void mysighandler(int sig)
{
printf("ERROR, Somebody Segmentation Faulted. About to Exit\n");
CREATE_COREDUMP();
exit(0);
}
crashtest::crashtest() {
char * errcond = NULL;
memcpy(errcond, "Crash This", 10);
}
crashtest::~crashtest() {}
int main(int argc, char** argv) {
struct sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_handler = &mysighandler;
sigaction(SIGSEGV, &sa, NULL);
crashtest ct;
return 0;
}
The point of the exercise is that the main code generates a segmentation fault occasionally which does not make sense because all the values are initialized. Therefore I am trying to discover why there is a segmentation fault and would like to get a core to track down the offending line of code. I cannot just kill since the code is required to recover and continue. That is why google-coredumper is thought to be used.
According to http://www.gossamer-threads.com/lists/linux/kernel/622686, it seems that coredumper in its current state is not usable anymore:
I believe, if I interpret the data on kernel.org correctly, this
change was made by Linus and shipped with 2.6.15.
Both perftools and coredumper need to locate all threads in the active
application in order to work. As libpthread has had changing and
poorly documented APIs to get this information, and as our intent is
to support all kernel versions and all libc versions, we resorted to
ptracing any process that is suspected to be one of our threads in
order to determine if it actually is. This has the added benefit of
finding all threads (including ones not managed by libpthread) and
of temporarily suspending them, so that we have a stable memory image
that we can inspect. Think of both tools as something like a
lightweight in-process debugger.
Obviously, special care has to be taken to not ptrace our own thread,
and to avoid any library calls that could deadlock.
Before the patch, attaching ptrace to my own threads was a valid
operation. With this new patch, I can no longer do that.
While reviewing bit of code, I came across a buggy std::terminate() handler
that wasn't terminating the program, but returning. Based on the documentation for std::set_terminate(), I think this falls within the realms of undefined - or at least implementation defined - behaviour.
Under Linux, and compiled using GCC, I found that cores were being dumped, which implies that some guardian angel was calling abort() or something similar on our behalf.
So I wrote the following test snippet, which confirmed my hunch. It looks like GCC or it's std library does wrap std::terminate() handlers so they do terminate the program.
#include <iostream>
#include <exception>
#include <dlfcn.h>
// Compile using
// g++ main.cpp -ldl
// Wrap abort() in my own implementation using
// dlsym(), so I can see if GCC generates code to
// call it if my std::terminate handler doesn't.
namespace std
{
void abort()
{
typedef void (*aborter)();
static aborter real_abort = 0x0;
if (0x0 == real_abort)
{
void * handle = 0x0;
handle = dlsym(RTLD_NEXT, "abort");
if (handle)
{
real_abort = (aborter )(handle);
}
}
std::cout << "2. Proof that GCC calls abort() if my buggy\n"
<< " terminate handler returns instead of terminating."
<< std::endl;
if (real_abort)
{
real_abort();
}
}
}
// Buggy terminate handler that returns instead of terminating
// execution via abort (or exit)
void buggyTerminateHandler()
{
std::cout << "1. In buggyTerminateHandler." << std::endl;
}
int main (int argc, char ** argv)
{
// Set terminate handler
std::set_terminate(buggyTerminateHandler);
// Raise unhandled exception
throw 1;
}
That a compiler (or library) would wrap std::terminate() handlers seems sensible to be, so at a guess I'd assume that most compilers do something along these lines.
Can anyone advise regarding the behaviour on Windows using Visual Studio or OS X using GCC?
Yesterday I asked question on stackoverflow, but I have not described it clearly, so I change the way to ask, maybe make the problem clear.
First, I modify the example get_sign.c which the klee provide, I include the unistd.h in the program, and call the function sleep() to make the thread pause, as follows
/*
* First KLEE tutorial: testing a small function
*/
#include <unistd.h>
int get_sign(int x) {
if (x == 0)
return 0;
if (x < 0)
return -1;
else
return 1;
}
int main() {
int a;
klee_make_symbolic(&a, sizeof(a), "a");
sleep(10);
return get_sign(a);
}
I use the "llvm-gcc" compile the get_sign.c, then use klee get_sign.o to execute the objectfile, the thread do not pause, means the sleep() does not work.
so I add a argument when I execute the get_sign.o, like this klee --libc=uclibc get_sign.o, unfortunately, the thread still don't suspend, moreover, the klee reports a error,
KLEE: ERROR: /home/lab/work/klee-uclibc/libc/signal/sigaction.c:58: failed external call: __syscall_rt_sigaction
KLEE: NOTE: now ignoring this error at this location
What can I do to solve this problem? thank you!
Looks like klee uses signals which can make sleep return sooner than expected, as indicated in http://www.delorie.com/gnu/docs/glibc/libc_445.html. This reference also provides ways to go around the limitation.
Solved: I upgraded from mingw 4.6.2 to 4.7.0 and it works perfectly, guess it was just a bug
I started to do some research on how terminate a multithreaded application properly and I found those 2 post(first, second) about how to use QueueUserAPC to signal other threads to terminate.
I thought I should give it a try, and the application keeps crashing when I throw the exception from the APCProc.
Code:
#include <stdio.h>
#include <windows.h>
class ExitException
{
public:
char *desc;
DWORD exit_code;
ExitException(char *desc,int exit_code): desc(desc), exit_code(exit_code)
{}
};
//I use this class to check if objects are deconstructed upon termination
class Test
{
public:
char *s;
Test(char *s): s(s)
{
printf("%s ctor\n",s);
}
~Test()
{
printf("%s dctor\n",s);
}
};
DWORD CALLBACK ThreadProc(void *useless)
{
try
{
Test t("thread_test");
SleepEx(INFINITE,true);
return 0;
}
catch (ExitException &e)
{
printf("Thread exits\n%s %lu",e.desc,e.exit_code);
return e.exit_code;
}
}
void CALLBACK exit_apc_proc(ULONG_PTR param)
{
puts("In APCProc");
ExitException e("Application exit signal!",1);
throw e;
return;
}
int main()
{
HANDLE thread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);
Sleep(1000);
QueueUserAPC(exit_apc_proc,thread,0);
WaitForSingleObject(thread,INFINITE);
puts("main: bye");
return 0;
}
My question is why does this happen?
I use mingw for compilation and my OS is 64bit.
Can this be the reason?I read that you shouldn't call QueueApcProc from a 32bit app for a thread which runs in a 64bit process or vice versa, but this shouldn't be the case.
EDIT: I compiled this with visual studio's c++ compiler 2010 and it worked flawlessly, it is possible that this is a bug in gcc/mingw?
I can reproduce the same thing with VS2005. The problem is that the compiler optimizes the catch away. Why? Because according to the C++ standard it's undefined what happens if an extern "C" function exits with an exception. So the compiler assumes that SleepEx (which is extern "C") does not ever throw. After inlining of Test::Test and Test::~Test it sees that the printf doesn't throw either, and consequently if something in this block exits via an exception
Test t("thread_test");
SleepEx(INFINITE,true);
return 0;
the behavior is undefined!
In MSVC the code doesn't work with the /EHsc switch in Release build, but works with /EHa or /EHs, which tell it to assume that C function may throw. Perhaps GCC has a similar flag.