I think my code wouldn't print the text
oh why come here!\n
but it does.
Is there something 'wrong' with system()? Because, when I removed it, the code ran as I wanted, halting up.
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
pthread_t id0, id1;
sem_t sp;
void *fun0(void *) {
// When erasing the following line "system("");",
// it block up, and doesn't print "oh why come here!\n".
// But with it, it print the text!
system("");
return NULL;
}
void *fun1(void *) {
sem_wait(&sp);
fprintf(stderr, "oh why come here!\n");
return NULL;
}
int main() {
sem_init(&sp, 0, 0);
pthread_create(&id0, 0, fun0, NULL);
pthread_create(&id1, 0, fun1, NULL);
void *stat0, *stat1;
pthread_join(id0, &stat0);
pthread_join(id1, &stat1);
return 0;
}
Compiler: gcc 4.1.2
Linux kernel: 2.6.18
I compiled it with gcc 4.6.3, kernel 3.2.0, it ran as I want also.
So I think it is because of gcc 4.1.2 or kernel 2.6.18.
The system() call has nothing to do with it. My psychic powers tell me that sem_wait is failing with an error code instead of waiting—check the return value. For example, I can reproduce your results on Mac OS X, because on Mac OS X, sem_init() always fails with ENOSYS ("Function not implemented"), which causes the call to sem_wait to then fail with EBADF ("Bad file descriptor").
If you add some error checking, you'll see where things go awry:
if(sem_init(&sp, 0, 0) < 0)
fprintf(stderr, "sem_init failed: %s\n", strerror(errno));
...
if(sem_wait(&sp) < 0)
fprintf(stderr, "sem_wait failed: %s\n", strerror(errno));
You should also crank up the warning level on your compiler—I definitely recommend using -Wall, and -Wextra -pedantic if you want to catch a lot more possible problems. Currently, your code invokes undefined behavior by failing to return values from your fun0 and fun1 functions, which -Wall would warn you about. This kind of error may not cause any obvious problems on x86, but on other architectures such as IA64, uninitialized garbage can be deadly.
Problem of your code is with sem_wait(), from sem_wait man page, it says:
"sem_wait() decrements (locks) the semaphore pointed to by sem. If the semaphore's value is greater than zero, then the decrement proceeds, and the function returns, immediately. If the semaphore currently has the value zero, then the call blocks until either it becomes possible to perform the decrement (i.e., the semaphore value rises above zero), or a signal handler interrupts the call."
On your code you've initialized with sp with 0, when sem_wait() decrements, it blocks and never returns since there's no other thread increments sp variable.
Related
Consider the following program:
#include <iostream>
#include <pthread.h>
#include <stdexcept>
#include <unistd.h>
static void* busy(void*)
{
int oldstate ;
auto result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldstate) ;
if (result != 0)
#ifdef NOEXCEPT
{ std::cerr << "pthread_setcanceltype" << std::endl ; abort() ; }
#else
throw std::runtime_error("pthread_setcanceltype") ;
#endif
while (true)
;
return nullptr ;
}
static pthread_t start()
{
pthread_t t ;
int result = pthread_create(&t,nullptr,busy,nullptr) ;
if (result != 0)
throw std::runtime_error("pthread_create") ;
return t ;
}
static void terminate(pthread_t t)
{
auto result = pthread_cancel(t) ;
if (result != 0)
throw std::runtime_error("pthread_cancel()") ;
result = pthread_join(t,nullptr) ;
if (result != 0)
throw std::runtime_error("pthread_join()") ;
}
int main()
{
auto t = start() ;
sleep(1) ; // may not cause an abort otherwise
terminate(t) ;
return 0 ;
}
This runs fine as long as no optimization (or -O1) is used, e.g. with g++ -std=c++11 -Wall -o test test.cc -pthread
However, with -O2 or -O3 the program aborts with the message above.
Also kind of interesting: it runs thru if compiled with -DNOEXCEPT. So it appears, if a thread is cancelled in a function that potentially [sic!] throws an exception, and if optimization is switched on, the program may abort. -- And I can't see any way to prevent this.
It's for me reproducible on amd64 gcc 4.8.4 (Ubuntu 14.04.3) and armv7l gcc 4.9.2 (Raspbian 4.9.2-10).
Can you reproduce this? Do you have an explanation? This behavior seems to be odd (at least to me). I'd be happy to receive some kind of feedback. Thank you!
On Linux (as on most OSes) exceptions are a language-agnostic feature, and pthread cancellation is implemented using language-agnostic exceptions (See e.g. Cancellation and C++ Exceptions).
When a pthread cancellation is delivered to a thread (using a signal, but you don't need to know that) the unwind machinery invokes all the installed personalities so that they can perform language-specific cleanup prior to the thread exiting. (This is pretty cool; it means that as in the above article you can insert a catch block for abi::__forced_unwind to detect - though not to prevent - a thread cancellation.)
The problem is that an asynchronous cancellation can occur at any instruction, and the C++ exception tables generated by g++ only handle exceptions occurring at instructions known to be capable of generating exceptions (i.e. but not only calls to exception-throwing functions). If an exception is generated at a point not covered by the C++ tables, the C++ personality panics and terminates the process (hence "terminate called without an active exception").
The reason this is influenced by optimization is that the C++ personality is installed lazily, but with higher optimization levels the compiler might decide to preemptively install the C++ personality. You can guarantee the crash even at lower optimization levels by exercising the C++ exception machinery e.g. with try { throw 0; } catch (int) {}.
The simplest fix is to ensure that the C++ personality is not installed in the thread you want to asynchronous cancel. You can ensure this by compiling the thread function as C and not calling any C++ functions from it.
A more hacky and highly unsupported solution is to ensure that all the asynchronous cancellation points (that is, all the instructions where the cancelled thread could be when the asynchronous cancellation is received) are in fact covered by the C++ unwind tables. Firstly you need to compile with -fnon-call-exceptions; secondly you have to ensure that every instruction that could be an asynchronous cancellation point is between two points known to be synchronous cancellation points, e.g. pthread_testcancel:
static void* busy(void*)
{
int oldstate ;
auto result = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&oldstate) ;
if (result != 0)
#ifdef NOEXCEPT
{ std::cerr << "pthread_setcanceltype" << std::endl ; abort() ; }
#else
throw std::runtime_error("pthread_setcanceltype") ;
#endif
pthread_testcancel();
for (unsigned i = 1; ; ++i)
if (i == 0)
pthread_testcancel();
return nullptr ;
}
Somebody wrote here that a program aborts "when a thread object goes out of scope and it is in joinable state".
That is what 39.3.1.3/1 [thread destructor] says actually:
If joinable(), calls std::terminate(). [...] Thus the programmer must ensure that the destructor is never executed while the thread is still joinable.
Running into a very strange issue with 2+ threads waiting on an interprocess_condition variable.
Boost 1.60.0
With 1 thread calling wait() and a 2nd calling notify_all(), everything works as expected.
When there are 2+ calling wait(), I get an assertion failure on do_wait() and the process exits.
Test.cpp:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <iostream>
using namespace boost::interprocess;
struct Data {
interprocess_mutex mux_;
interprocess_condition cond_;
};
int main(int argc, char *argv[]) {
if (argc > 1 && atoi(argv[1]) == 0) {
struct shm_remove {
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove() { shared_memory_object::remove("MySharedMemory"); }
} remover;
managed_shared_memory seg(create_only, "MySharedMemory", 65536);
Data *const d = seg.construct<Data>(unique_instance)();
scoped_lock<interprocess_mutex> lock(d->mux_);
std::cout << "Waiting" << std::endl;
d->cond_.wait(lock);
} else if (argc > 1 && atoi(argv[1]) == 1) {
managed_shared_memory seg(open_only, "MySharedMemory");
std::pair<Data *, std::size_t> res = seg.find<Data>(unique_instance);
scoped_lock<interprocess_mutex> lock(res.first->mux_);
std::cout << "Waiting" << std::endl;
res.first->cond_.wait(lock);
} else {
managed_shared_memory seg(open_only, "MySharedMemory");
std::pair<Data *, std::size_t> res = seg.find<Data>(unique_instance);
scoped_lock<interprocess_mutex> lock(res.first->mux_);
std::cout << "Notifying" << std::endl;
res.first->cond_.notify_all();
}
}
Compiled as:
$ clang++ -I/usr/local/include test.cpp
Running with 1 wait() and 1 notify():
$ ./a.out 0&
[8] 25889
Waiting
$ ./a.out 2&
[9] 25901
Notifying
[8]- Done ./a.out 0
[9]+ Done ./a.out 2
Running with 2 waits:
$ ./a.out 0&
[8] 25986
Waiting
$ ./a.out 1&
[9] 25998
Waiting
Assertion failed: (res == 0), function do_wait, file /usr/local/include/boost/interprocess/sync/posix/condition.hpp, line 175.
Tested on OSX El Capitan
$ uname -a
Darwin LUS-JOHUGHES2 15.3.0 Darwin Kernel Version 15.3.0: Thu Dec 10 18:40:58 PST 2015; root:xnu-3248.30.4~1/RELEASE_X86_64 x86_64
I also tried the above example on an Ubuntu Trusty machine and all examples work as expected, leading me to believe there is an issue with the OSX implementation. I have not tried it on Windows.
Did some digging and found a definite answer to the problem.
The boost assertion error above is failing when the second process calls do_wait(), which calls pthread_wait() which returns immediately with EINVAL (instead of a successful 0).
In OSX's pthread implementation, the condition variable stores a raw pointer to the mutex variable. The first call to pthread_wait() in the first process sets this pointer. The second call to pthread_wait() checks this stored mutex pointer against the mutex pointer passed into pthread_wait(). {Can be found in the source here: https://opensource.apple.com/source/libpthread/libpthread-137.1.1/src/pthread_cond.c}
Since the two processes have mapped the shared mutex and condition variables in different address spaces, the second call to pthread_wait() will never work, since it compares raw pointers.
Thus the 2 options to make this work are as follows:
Use Fixed Address Mapping: http://www.boost.org/doc/libs/1_60_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_region.mapped_region_fixed_address_mapping which guarantees that the mapped regions will be at the same address, and thus raw pointers will work, or
Instead of exec()'ing new processes, use fork() which means that the child process will have a copy of the original segment manager, mapped to the same address, and thus raw pointers will work.
I didn't dig much into the glibc pthreads code to see what they do differently than Apple, so I'm not sure why the original example works on Linux but not OSX.
I think the Boost docs would definitely benefit with a paragraph discussing this pitfall.
This is a bug both on Darwin's C library and Boost.Interprocess. First, that C library claims it's posix-compliant and supports process shared memory condition variables, which is false (as it uses a raw pointer to store the address of the mutex). Second, Boost.Interprocess should detect this platform as a buggy one, should disable the use of pthreads and fallback to emulation.
In boost/interprocess/detail/workaround.hpp, you will find a comment saying:
//Mac Os X < Lion (10.7) might define _POSIX_THREAD_PROCESS_SHARED but there is no real support.
Some old reports claimed that newer macos versions really support process shared condition variables, but this claim is false, so the __APPLE__ section should be just:
#define BOOST_INTERPROCESS_BUGGY_POSIX_PROCESS_SHARED
I'm trying to make a Python program that interfaces with a different crashy process (that's out of my hands). Unfortunately the program I'm interfacing with doesn't even crash reliably! So I want to make a quick C++ program that crashes on purpose but I don't actually know the best and shortest way to do that, does anyone know what to put between my:
int main() {
crashyCodeGoesHere();
}
to make my C++ program crash reliably
The abort() function is probably your best bet. It's part of the C standard library, and is defined as "causing abnormal program termination" (e.g, a fatal error or crash).
Try:
raise(SIGSEGV); // simulates a standard crash when access invalid memory
// ie anything that can go wrong with pointers.
Found in:
#include <signal.h>
Dividing by zero will crash the application:
int main()
{
return 1 / 0;
}
*((unsigned int*)0) = 0xDEAD;
Well, are we on stackoverflow, or not?
for (long long int i = 0; ++i; (&i)[i] = i);
(Not guaranteed to crash by any standards, but neither are any of the suggested answers including the accepted one since SIGABRT could have been caught anyway. In practice, this will crash everywhere.)
throw 42;
Just the answer... :)
assert(false); is pretty good too.
According to ISO/IEC 9899:1999 it is guaranteed to crash when NDEBUG is not defined:
If NDEBUG is defined [...] the assert macro is defined simply as
#define assert(ignore) ((void)0)
The assert macro is redefined according to the current state of NDEBUG each time that is included.
[...]
The assert macro puts diagnostic tests into programs; [...] if expression (which shall have a scalar type) is false [...]. It
then calls the abort function.
Since a crash is a symptom of invoking undefined behaviour, and since invoking undefined behaviour can lead to anything, including a crash, I don't think you want to really crash your program, but just have it drop into a debugger. The most portable way to do so is probably abort().
While raise(SIGABRT) has the same effect, it is certainly more to write. Both ways however can be intercepted by installing a signal handler for SIGABRT. So depending on your situation, you might want/need to raise another signal. SIGFPE, SIGILL, SIGINT, SIGTERM or SIGSEGV might be the way to go, but they all can be intercepted.
When you can be unportable, your choices might be even broader, like using SIGBUS on linux.
The answer is platform specific and depends on your goals. But here's the Mozilla Javascript crash function, which I think illustrates a lot of the challenges to making this work:
static JS_NEVER_INLINE void
CrashInJS()
{
/*
* We write 123 here so that the machine code for this function is
* unique. Otherwise the linker, trying to be smart, might use the
* same code for CrashInJS and for some other function. That
* messes up the signature in minidumps.
*/
#if defined(WIN32)
/*
* We used to call DebugBreak() on Windows, but amazingly, it causes
* the MSVS 2010 debugger not to be able to recover a call stack.
*/
*((int *) NULL) = 123;
exit(3);
#elif defined(__APPLE__)
/*
* On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
* trapped.
*/
*((int *) NULL) = 123; /* To continue from here in GDB: "return" then "continue". */
raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */
#else
raise(SIGABRT); /* To continue from here in GDB: "signal 0". */
#endif
}
The only flash I had is abort() function:
It aborts the process with an abnormal program termination.It generates the SIGABRT signal, which by default causes the program to terminate returning an unsuccessful termination error code to the host environment.The program is terminated without executing destructors for objects of automatic or static storage duration, and without calling any atexit( which is called by exit() before the program terminates)function. It never returns to its caller.
I see there are many answers posted here that will fall into lucky cases to get the job done, but none of them are 100% deterministic to crash. Some will crash on one hardware and OS, the others would not.
However, there is a standard way as per official C++ standard to make it crash.
Quoting from C++ Standard ISO/IEC 14882 §15.1-7:
If the exception handling mechanism, after completing the
initialization of the exception object but before the activation of a
handler for the exception, calls a function that exits via an
exception, std::terminate is called (15.5.1).
struct C {
C() { }
C(const C&) {
if (std::uncaught_exceptions()) {
throw 0; // throw during copy to handler’s exception-declaration object (15.3)
}
}
};
int main() {
try {
throw C(); // calls std::terminate() if construction of the handler’s
// exception-declaration object is not elided (12.8)
} catch(C) { }
}
I have written a small code to demonstrate this and can be found and tried on Ideone here.
class MyClass{
public:
~MyClass() throw(int) { throw 0;}
};
int main() {
try {
MyClass myobj; // its destructor will cause an exception
// This is another exception along with exception due to destructor of myobj and will cause app to terminate
throw 1; // It could be some function call which can result in exception.
}
catch(...)
{
std::cout<<"Exception catched"<<endl;
}
return 0;
}
ISO/IEC 14882 §15.1/9 mentions throw without try block resulting in implicit call to abort:
If no exception is presently being handled, executing a
throw-expression with no operand calls std::terminate()
Others include :
throw from destructor: ISO/IEC 14882 §15.2/3
*( ( char* ) NULL ) = 0;
This will produce a segmentation fault.
This one is missing:
int main = 42;
This crashes on my Linux system, because string literals are stored in read only memory:
0[""]--;
By the way, g++ refuses to compile this. Compilers are getting smarter and smarter :)
What about stack overflow by a dead loop recursive method call?
#include <windows.h>
#include <stdio.h>
void main()
{
StackOverflow(0);
}
void StackOverflow(int depth)
{
char blockdata[10000];
printf("Overflow: %d\n", depth);
StackOverflow(depth+1);
}
See Original example on Microsoft KB
This is a more guaranteed version of abort presented in above answers.It takes care of the situation when sigabrt is blocked.You can infact use any signal instead of abort that has the default action of crashing the program.
#include<stdio.h>
#include<signal.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
sigset_t act;
sigemptyset(&act);
sigfillset(&act);
sigprocmask(SIG_UNBLOCK,&act,NULL);
abort();
}
This is the snippet provided by Google in Breakpad.
volatile int* a = reinterpret_cast<volatile int*>(NULL);
*a = 1;
int i = 1 / 0;
Your compiler will probably warn you about this, but it compiles just fine under GCC 4.4.3
This will probably cause a SIGFPE (floating-point exception), which perhaps is not as likely in a real application as SIGSEGV (memory segmentation violation) as the other answers cause, but it's still a crash. In my opinion, this is much more readable.
Another way, if we're going to cheat and use signal.h, is:
#include <signal.h>
int main() {
raise(SIGKILL);
}
This is guaranteed to kill the subprocess, to contrast with SIGSEGV.
int* p=0;
*p=0;
This should crash too. On Windows it crashes with AccessViolation and it should do the same on all OS-es I guess.
Although this question already has an accepted answer...
void main(){
throw 1;
}
Or... void main(){throw 1;}
int main(int argc, char *argv[])
{
char *buf=NULL;buf[0]=0;
return 0;
}
Writing to a read-only memory will cause segmentation fault unless your system don't support read-only memory blocks.
int main() {
(int&)main = 0;
}
I have tested it with MingGW 5.3.0 on Windows 7 and GCC on Linux Mint. I suppose that other compilers and systems will give a similar effect.
Or another way since we're on the band wagon.
A lovely piece of infinite recursion. Guaranteed to blow your stack.
int main(int argv, char* argc)
{
return main(argv, argc)
}
Prints out:
Segmentation fault (core dumped)
void main()
{
int *aNumber = (int*) malloc(sizeof(int));
int j = 10;
for(int i = 2; i <= j; ++i)
{
aNumber = (int*) realloc(aNumber, sizeof(int) * i);
j += 10;
}
}
Hope this crashes. Cheers.
int main()
{
int *p=3;
int s;
while(1) {
s=*p;
p++;
}
}
A stylish way of doing this is a pure virtual function call:
class Base;
void func(Base*);
class Base
{
public:
virtual void f() = 0;
Base()
{
func(this);
}
};
class Derived : Base
{
virtual void f()
{
}
};
void func(Base* p)
{
p->f();
}
int main()
{
Derived d;
}
Compiled with gcc, this prints:
pure virtual method called
terminate called without an active exception
Aborted (core dumped)
You can use of assembly in your c++ code BUT INT 3 is only for x86 systems other systems may have other trap/breakpoint instructions.
int main()
{
__asm int 3;
return 0;
}
INT 3 causes an interrupt and calls an interrupt vector set up by the OS.
Use __builtin_trap() in GCC or clang, or __debugbreak() in MSVC. Not handling these breakpoints/traps will lead to an unhandled breakpoint exception/crash.
Other suggestions that use abort() or exit(): those may be handled by other threads, making it more difficult to see the stack of the thread that propagated the crash.
#include <thread>
void intentionalCrash()
{
auto noop = [](){return;};
// Thread t1 is in a joinable state.
// When program returns t1 will be out of scope.
// Destructing a joinable thread creates a crash.
std::thread t1(noop);
}
int main()
{
intentionalCrash();
return 0;
}
Simple buffer overflow code that will cause the program to crash
int main()
{
int n[0];
n[2] = 0;
}
I am trying to port some code using VC++'s try-except statement to MinGW:
bool success = true;
__try {
//...
} __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode())
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH) {
success = false;
_resetstkoflw();
}
return success;
Is it possible to write code that catches a stack overflow exception using MinGW g++?
You would need to manually call the Windows API functions which register exception handling; namely, AddVectoredExceptionHandler. Note that by using MinGW which does not respect SEH exceptions, throwing any SEH exception or attempting to catch any such exception will result in undefined behavior, because the normal C++ stack unwinding semantic isn't done. (How does Windows know to nuke all those std::strings on the stack?)
You would also need to call RemoveVectoredExceptionHandler at the end of the time you want that SEH exception handler to be called.
Generally MinGW is lacking in support of Windows features like SEH and COM. Any reason you're trying to use that instead of MSVC++ (given that both compilers are free?)
This isn't well known, but the header file <excpt.h> in MinGW and MinGW-w64 provides macros __try1 and __except1 to produce gcc inline assembly for handling exceptions. These macros are not documented and are not easy to use. It gets worse. The x86_64 editions of __try1 and __except1 aren't compatible with the 32-bit editions. They use different callbacks with different arguments and different return values.
After a few hours, I almost had working code on x86_64. I needed to declare a callback with the same prototype as _gnu_exception_handler in MinGW's runtime. My callback was
long CALLBACK
ehandler(EXCEPTION_POINTERS *pointers)
{
switch (pointers->ExceptionRecord->ExceptionCode) {
case EXCEPTION_STACK_OVERFLOW:
return EXCEPTION_EXECUTE_HANDLER;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
And my try-except code was
__try1 (ehandler) {
sum = sum1to(n);
__asm__ goto ( "jmp %l[ok]\n" :::: ok);
} __except1 {
printf("Stack overflow!\n");
return 1;
}
ok:
printf("The sum from 1 to %u is %u\n", n, sum);
return 0;
It was working until I enabled optimization with gcc -O2. This caused assembler errors so my program no longer compiled. The __try1 and __except1 macros are broken by an optimization in gcc 5.0.2 that moves functions from .text to a different section.
When the macros did work, the control flow was stupid. If a stack overflow happened, the program jumped through __except1. If a stack overflow didn't happen, the program fell through __except1 to the same place. I needed my weird __asm__ goto to jump to ok: and prevent the fall-through. I can't use goto ok; because gcc would delete __except1 for being unreachable.
After a few more hours, I fixed my program. I copied and modified the assembly code to improve the control flow (no more jump to ok:) and to survive gcc -O2 optimization. This code is ugly, but it works for me:
/* gcc except-so.c -o except-so */
#include <windows.h>
#include <excpt.h>
#include <stdio.h>
#ifndef __x86_64__
#error This program requires x86_64
#endif
/* This function can overflow the call stack. */
unsigned int
sum1to(unsigned int n)
{
if (n == 0)
return 0;
else {
volatile unsigned int m = sum1to(n - 1);
return m + n;
}
}
long CALLBACK
ehandler(EXCEPTION_POINTERS *pointers)
{
switch (pointers->ExceptionRecord->ExceptionCode) {
case EXCEPTION_STACK_OVERFLOW:
return EXCEPTION_EXECUTE_HANDLER;
default:
return EXCEPTION_CONTINUE_SEARCH;
}
}
int main(int, char **) __attribute__ ((section (".text.startup")));
/*
* Sum the numbers from 1 to the argument.
*/
int
main(int argc, char **argv) {
unsigned int n, sum;
char c;
if (argc != 2 || sscanf(argv[1], "%u %c", &n, &c) != 1) {
printf("Argument must be a number!\n");
return 1;
}
__asm__ goto (
".seh_handler __C_specific_handler, #except\n\t"
".seh_handlerdata\n\t"
".long 1\n\t"
".rva .l_startw, .l_endw, ehandler, .l_exceptw\n\t"
".section .text.startup, \"x\"\n"
".l_startw:"
:::: except );
sum = sum1to(n);
__asm__ (".l_endw:");
printf("The sum from 1 to %u is %u\n", n, sum);
return 0;
except:
__asm__ (".l_exceptw:");
printf("Stack overflow!\n");
return 1;
}
You might wonder how Windows can call ehandler() on a full stack. All those recursive calls to sum1to() must remain on the stack until my handler decides what to do. There is some magic in the Windows kernel; when it reports a stack overflow, it also maps an extra page of stack so that ntdll.exe can call my handler. I can see this in gdb, if I put a breakpoint on my handler. The stack grows down to address 0x54000 on my machine. The stack frames from sum1to() stop at 0x54000, but the exception handler runs on an extra page of stack from 0x53000 to 0x54000. Unix signals have no such magic, which is why Unix programs need sigaltstack() to handle a stack overflow.
You might want to look into LibSEH for adding Structured Exception Handling compatibility for MinGW.
MinGW doesn't support the keywords for structured exceptions; but, as Billy O'Neal says in his answer, you can call certain native functions to get the same effect.
The question is whether you want the same effect. I strongly believe that structured exceptions are a mistake. The list of structured exceptions that the operating system will tell you about include things like "tried to divide an integer by 0," "couldn't use the HANDLE parameter passed to a function," "tried to execute an illegal machine code instruction," and "tried to access memory without permission to do so." You really can't do anything intelligent about these errors, but structured exceptions give you the opportunity to (1) claim that you have and (2) allow the program to hobble along a little longer. It's far better to find out why the code tried to divide by 0, passed an invalid HANDLE parameter, tried to access memory without permission to do so, etc. and fix the code to never do that.
There is an argument that you could use structured exceptions to detect problems, display a dialog box, and exit. I'm not sure how this is better than letting the operating system display a dialog box and exit the program (especially if the operating system sends you a minidump in the process), which is the default behavior for unhandled exceptions.
Some errors aren't recoverable.
I am trying to make a small thread example. I want to have a variable and each thread try to increment it and then stop once it gets to a certain point. Whenever the variable is locked, I want some sort of message to be printed out like "thread x trying to lock, but cannot" so that I KNOW it's working correctly. This is my first day coding threads so feel free to point out anything unnecessary in the code here -
#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define NUM_THREADS 2
pthread_t threads[NUM_THREADS];
pthread_mutex_t mutexsum;
int NUMBER = 0;
void* increaseByHundred(void* threadid) {
if(pthread_mutex_lock(&mutexsum))
cout<<"\nTHREAD "<<(int)threadid<<" TRYING TO LOCK BUT CANNOT";
else {
for(int i=0;i<100;i++) {
NUMBER++;
cout<<"\nNUMBER: "<<NUMBER;
}
pthread_mutex_unlock(&mutexsum);
pthread_exit((void*)0);
}
}
int main(int argc, char** argv) {
int rc;
int rc1;
void* status;
pthread_attr_t attr;
pthread_mutex_init(&mutexsum, NULL);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
rc = pthread_create(&threads[0], &attr, increaseByHundred, (void*)0);
rc1 = pthread_create(&threads[1], &attr, increaseByHundred, (void*)1);
pthread_attr_destroy(&attr);
while(NUMBER < 400)
pthread_join(threads[0], &status);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}
I was following a tutorial found here https://computing.llnl.gov/tutorials...reatingThreads
and tried to adapt their mutex example to this idea. The code increments it up to 199 and then stops. I'm guessing because the threads are only doing their routine once. Is there a way make them just do their routine other than when you create them so I could say
while something
do your routine
?
I have the pthread_join there just because it was similar to what that tutorial had on theirs. I don't really even get it that clearly though. I'm pretty sure that line is the problem...I just don't know how to fix it. Any help is appreciated.
Whenever the variable is locked, I want some sort of message to be printed out like "thread x trying to lock, but cannot" so that I KNOW it's working correctly.
Why do you want that? You are just learning about threads. Learn the basics first. Don't go diving off the deep end into pthread_mutex_trylock or mutexes configured for error checking. You need to learn to walk before you can learn how to run.
The basics involves a mutex initialized use with default settings and using pthread_mutex_lock to grab the lock. With the default settings, pthread_mutex_lock will only return non-zero if there are big, big problems. There are only two problems that can occur here: Deadlock, and a bad mutex pointer. There is no recovery from either; the only real solution is to fix the code. About the only thing you can do here is to throw an exception that you don't catch, call exit() or abort(), etc.
That some other thread has locked the mutex is not a big problem. It is not a problem at all. pthread_mutex_lock will block (e.g., go to sleep) until the lock becomes available. A zero return from pthread_mutex_lock means that the calling thread now has the lock. Just make sure you release the lock when you are done working with the protected memory.
Edit
Here's a suggestion that will let you see that the threading mechanism is working as advertised.
Upon entry to increaseByHundred print a time-stamped message indicating entry to the function. You probably want to use C printf here rather than C++ I/O. printf() and related functions are thread-safe. C++ 2003 I/O is not.
After a successful return from pthread_mutex_lock print another time-stamped message indicating that a successful lock.
sleep() for a few seconds and then print yet another time-stamped message prior to calling pthread_mutex_unlock().
Do the same before calling pthread_exit().
One last comment: You are checking for an error return from pthread_mutex_lock. For completeness, and because every good programmer is paranoid as all get out, you should also check the return status from pthread_mutex_unlock.
What about pthread_exit? It doesn't have a return status. You could print some message after calling pthread_exit, but you will only reach that statement if you are using a non-compliant version of the threads library. The function pthread_exit() cannot return to the calling function. Period. Worrying about what happens when pthreads_exit() returns is a tinfoil hat exercise. While good programmers should be paranoid beyond all get out, they should not be paranoid schizophrenic.
pthread_mutex_lock will normally just block until it acquire the lock, and that's why the line cout<<"\nTHREAD "<<(int)threadid<<" TRYING TO LOCK BUT CANNOT"; is not ran.
You also have problems in
while(NUMBER < 400)
pthread_join(threads[0], &status);
because you just have 2 threads and number will never reach 400. You also want to join thread[0] on first iteration, then thread[1]...
pthread_mutex_trylock():
if (pthread_mutex_trylock(&mutex) == EBUSY) {
cout << "OMG NO WAY ITS LOCKED" << endl;
}
It is also worth noting that if the mutex is not locked, it will be able to acquire the lock and then it will behave like a regular pthread_mutex_lock().