I have a multi-threaded application for retrieving database information and storing data as linked list of objects which i use further to do some operations on them and output the results. During the course of execution, I am bound to encounter exceptions like Access Violation due to the nature of pointers.
I certainly know these exceptions (Hardware or Software) are not caught by regular try catch in C++ and also know that we have avoid such exceptions by reprogramming culprit section.. But because i dont have control of data in database, sometimes I end up getting the exception and whole program crashes.
I would like to know if there a way to notify the user of Access Violation and preventing the affected thread from crashing other threads or whole process.
int ex;
pthread_mutex_t lk;
void sighandler(int a){
pthread_mutex_unlock(&lk);
}
static void *func1(void * arg) {
while(1) {
pthread_mutex_lock(&lk);
if(ex<=0) {
try {
char *p=0;*p = 0;
} catch(...) {
printf("eerr");
}
pthread_mutex_unlock(&lk);
break;
}
ex--;
pthread_mutex_unlock(&lk);
}
return 0;
}
static void *func2(void * arg) {
while(1) {
pthread_mutex_lock(&lk);
if(ex<=-100) {
pthread_mutex_unlock(&lk);
break;
}
ex-=2;
pthread_mutex_unlock(&lk);
}
return 0;
}
int main(void)
{
signal(SIGSEGV,sighandler);
ex=100;
pthread_t pth[2];
pthread_mutex_init(&lk,NULL);
pthread_create(&pth[0],NULL,func1,NULL);
pthread_create(&pth[1],NULL,func2,NULL);
pthread_join(pth[0],NULL);
pthread_join(pth[1],NULL);
return 0;
}
I tried to create simpler version of what i would like to know.. There would definitely be access violation in func1 (*p=0) but I would like the func2 to run unhindered while notifying the user of access violation through some kind of log or through controller thread.
Thank You
Related
Recently, due to an error in my code, I created a recursive call (infinite loop, in fact). One of the methods involved in the loop used a pre-computed task. It can be summarized as:
ConcurrentHashMap<String, FutureTask<Integer>> cache = new ConcurrentHashMap<>();
int method1() {
var task = cache.computeIfAbsent("key", k -> new FutureTask<>(this::method2));
task.run();
try {
return task.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
int method2() {
if (1 + 1 != 4) { // this wasn't so obvious of course...
return method1();
}
return 1;
}
In short: FutureTask's get() was called while inside its run() execution.
To my surprise, it resulted in a deadlock, as get() makes no checks and parks the current thread unconditionally.
I know I shot myself in the foot with low-level primitives, but is there a reason or use case why get() doesn't make a check and
throw an exception when called from the same thread as the runner thread of the task?
I need to stop the program flow in the middle, and I am currently using an exception for this. This flow is the legal flow and I want to know if I can do it without using an exception.
This is an example of my code, and I cannot change func_2 and func_1:
#include "stdio.h"
void func_3()
{
printf("i am func_3\n");
throw 20;
printf("i am not supposed to be here\n");
}
void func_2()
{
printf("i am func_2\n");
func_3();
printf("i am not supposed to be here\n");
}
void func_1()
{
printf("i am func_1\n");
func_2();
printf("i am not supposed to be here\n");
}
int main()
{
try
{
func_1();
}
catch (int e)
{
printf("i am supposed to be here\n");
}
catch (...)
{
printf("i am not supposed to be here\n");
}
}
I assume that you want to handle an exceptional case and are looking for an alternative to exceptions. I.e. I hope you don't want to continue with the program "normally" after handling your exceptional case, which is possible but not recommended to implement with exceptions.
Possible but not recommended alternatives to exceptions are:
When you want to stop your whole application, then you can use std::exit(0);. You can implement your "catch"-code in a function which you call instead of your "throw"-statement, and call std::exit(0); at the end of that function (or use another exit code to indicate an "unsuccessful" exit). Or you implement an exit handler and register it using std::atexit(&handle_exit);.
Alternative to std::exit(<something>); is abort(); which throws the POSIX signal "SIGABRT" to indicate abnormal termination (which is the default behavior if your program throws and doesn't catch an exception). Your "catch"-code would then go in a signal handler which you register using the POSIX functions. Note that this requires a POSIX system and is thus not as portable as other solutions.
Another (similar) option is to use the "terminate" mechanism: Call std::terminate(); when you would normally throw your exception. Put your "catch"-code in a "terminate handler" function with signature void(*)(), i.e. no parameters and no return value, let's call the function void handle_terminate(). Install a terminate handler using std::set_terminate(&handle_terminate);. I didn't try that one, however, and it sounds damn ugly.
You could implement an exception-like behavior using assembly instructions, but please do not try this at home, as the behavior of such code is highly implementation defined (if not undefined), and way too ugly to implement.
In short, you can't (well ... you could, by using jumps instead, but then you would have two problems to solve).
The exception solution is the one to use, but do not throw a number (a number - especially a magical number in this case doesn't tell you anything).
Instead, define a struct func_3_interrupted {}; minimalistic structure, whose type name tells you it is an "interruption" of func_3, and catch that instead; The structure should be empty (or close to empty) and it should probably not inherit from the std::exception hierarchy.
Return can be used to return to the caller and stop the function being executed
int GLOBAL_FLAG = 1;
function called_function(){
printf("Inside Function")
if(/*some condition*/)
{
GLOBAL_FLAG = 0;
return;
}
/*Normal function code*/
}
int main(){
{
called_function();
if(GLOBAL_FLAG == 1)/*continue program execution*/
printf("Function had been executed.Back to normal flow")
}
So once the return statement is encountered it goes back to the caller that is main here and continues executing rest of the statements in main function.
Basically, how to catch exceptions on mac/linux? That is, exceptions, that are not intrinsic to the language, like segfaults & integer division. Compiling on MSVC, __try __except is perfect because the stack handling allows to catch exceptions and continue execution lower down the stack.
Now, i would like to extend my program to other platforms (mainly the ones mentioned), but i have no idea how exception handling works on these platforms work. As far as i understand, it's handled through posix signals? And as of such, wont allow to handle exception and continue lower down the stack?
Edit: Would this be valid (pseudo code)? As i see it, i leave C++ blocks correctly and thus dont indulge myself in UB.
jmp_buf buffer;
template< typename func >
protected_code(func f) {
if(!setjmp(buffer) {
f();
}
else
{
throw std::exception("exception happened in f()"):
}
}
void sig_handler() {
longjmp(buffer);
}
int main() {
sigaction(sig_handler);
try {
protected_code( [&]
{
1/0;
}
);
}
catch(const std::exception & e) {
...
}
}
Edit 2:
Wow for some reason i never thought of just throwing a C++ exception from the signal handler, no need to use longjmp/setjmp then. It of course relies on the fact that the thread calling the signal handler is the same stack and thread that faulted. Is this defined/guaranteed somewhere?
Code example:
void sig_handler(int arg) {
throw 4;
}
int main() {
signal(SIGFPE, sig_handler);
try {
int zero = 1;
zero--;
int ret = 1/zero;
} catch(int x) {
printf("catched %d\n", x);
}
return 0;
}
In Unix, you'd catch processor faults with signal handlers, using the sigaction function to install a suitable handler for the signal that you want to handle.
(I think you mean __try ... __except rather than __try ... __catch.
In the code below i use try/catch in the python module code. In the try block i have a simple error (memory access violation) and trying to catch the corresponding exception and to terminate the program quietly without generation of the .stackdump file. However the latter is still generated what implies that try/catch construct does not do its job. How could i avoid generating .stackdump file and exit the program without errors when the improper operation (like one in the code) is met?
P.S. i'm compiling the code in cygwin with gcc and boost.python
It is interesting that it doesn't work only in case x[3]=2, but works for all other cases: e.g. x[4]=2 or x[20]=2 or, obviously, x[2]=2.
#include <boost/python.hpp>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace boost::python;
class Hello
{
std::string _msg;
public:
Hello(std::string msg){_msg = msg;}
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ exit(0); }
}
};
BOOST_PYTHON_MODULE(xyz)
{
class_<Hello>("Hello", init<std::string>())
.def("run",&Hello::run)
;
}
EDIT:
According to what Maciek has suggested i tried the following trick:
Make signal handling function to throw an exception, but not exit
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
throw 1;
// exit(0);
}
And now try to enclose a possibly problematic function in try/catch block (signal function is placed in class constructor):
class Hello
{
std::string _msg;
public:
Hello(std::string msg){
_msg = msg;
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
}
void set(std::string msg) { this->_msg = msg; }
std::string greet() { return _msg; }
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ cout<<"error in function run()\n"; exit(0); }
}
};
However such a trick doesn't work as i expected it produces the following output:
SIGNAL 6
terminate called after throwing an instance of 'int'
SIGNAL 6
terminate called recursively
SIGNAL 6
terminate called recursively
....
(and many more times the same)
So the exception is thrown, but everything finishes before it has been caught. Is there any way to let it be caught before terminating the process?
You can only catch exceptions that are thrown. An invalid pointer access doesn’t throw an exception, it simply causes undefined behaviour, and in your particular case it results in a stack dump.
If you want to catch such a situation situation, use std::vector and the at function to access items. This will throw std::out_of_range when used with an invalid index. However, it’s usually better to avoid the possibility of such accesses a priori since they are usually indicative of a bug in your program, and bugs should not be handled via exceptions, they should be removed from the code.
On linux core dumps are generated by signal handlers with default action set to core (SIGABRT, SIGSEGV, ...). If you want to avoid core dump you can always capture/ignore those signals. It should work on Cygwin stackdumps as well. But you will still probably get some nasty message as output.
EDIT:
#include <signal.h>
// [...]
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
exit(0);
}
int main(int argc, char* argv[]) {
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
Hello h("msg");
h.run();
}
Here is a code below. The code is not complete, I omitted releasing resources part and implementation of QueryRes logic.
#define N 5
/*simply resources manager which has N shared resources*/
class ResourceManager
{
public:
ResourceManager()
{
for (int i = 0; i < N; ++i)
resources[i] = CreateMutex(NULL, FALSE, NULL);
}
/*CreateMutex for on resources array in ctor*/
/*CloseHandle() in dtor and ReleaseMutex in another function which is called after QueryRes*/
void QueryRes(int i)
{
WaitForSingleObject(resources[i], INFINITE); //(*) Here is the problem
}
private:
HANDLE resources[N];
};
/*User who asks for resource time-to-time*/
class User
{
public:
User(ResourceManager& res_holder_, int res_num) : resource_holder(resource_holder), resource_to_query(res_num) {}
void WorkWithResource()
{
while(1)
{
resource_holder.QueryRes(resource_to_query);
}
}
static void Run (void* params)
{
static_cast<User*>(params)->WorkWithResource();
}
private:
ResourceManager& resource_holder;
int resource_to_query;
};
int main()
{
ResourceManager resource_manager;
User* users[5];
HANDLE threads[5];
for (size_t i = 0 ; i < 5; ++i)
{
users[i] = new User(resource_manager, i % 5);
threads[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&User::Run, users[i], 0, NULL);
}
WaitForMultipleObjects(5, threads, true, INFINITE);
return 0;
}
At (*) place I get an "access violation exception" when the function does WaitForSingleObject on already locked mutex.
I also tried
while(WaitForSingleObject(resources[i], INFINITE) != WAIT_OBJECT_0)
and got the same result.
Why do I get the exception?
I tried vc 2003, 2008 and 2010. I can't use boost/pthreads/etc.
Thank you.
The error lies in the constructor of
User(ResourceManager& res_holder_, int res_num) : resource_holder(resource_holder), resource_to_query(res_num) { }
You should have
User(ResourceManager& res_holder_, int res_num) : resource_holder(**res_holder_**), resource_to_query(res_num) { }
instead !
When you get an access violation (or segfault in other platforms, although generically speaking this is a bad pointer dereference), often the reason is obvious from looking at the code... In this case nothing pops out at me from what you've posted. My guess based on what you said is something smashed the stack.
However, a bit of advice... When you see an access violation you can't explain, the first step is not to post to Stack Overflow. Look at it in a debugger! If you download "Debugging tools for Windows" from Microsoft and use "windbg", and learn how to use it, it will tell you more about this crash than you ever thought you could know - what the bad address it tried to access was, disassembly of WaitForMultipleObjects so you can see what it's doing and where the address came from, etc. I usually find with a few k, r, u, and dq commands in windbg, the cause for a bad pointer dereference becomes pretty obvious.