From kde-mac Sun Sep 25 12:34:49 2011 From: =?ISO-8859-1?Q?Jonas_B=E4hr?= Date: Sun, 25 Sep 2011 12:34:49 +0000 To: kde-mac Subject: Re: [KDE/Mac] [CODE] Multithreaded SIGSEGV signal handling, Message-Id: <8AC44E9E-36AA-45B3-B148-8321F20D95CD () web ! de> X-MARC-Message: https://marc.info/?l=kde-mac&m=131695411332097 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--Apple-Mail-5--655527130" --Apple-Mail-5--655527130 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit Hi, Am 25.09.2011 um 01:37 schrieb Michael Pyne: > [...] > With that said I don't think the code uses as many POSIX options as > the rest > of KSharedDataCache (e.g. process-shared mutexes as unimplemented on > Mac OS X) > but I wanted to give a chance for you guys to test the prototype code > beforehand and let me know if there's problems. > > You'll want to compile with something like this: > $CXX -O2 -o sigcatcher -lrt -pthread sigcatcher.cpp Here is the first issue: librt doesn't exist here (Mac OS X 10.5 "Leopard"). However, the code compiles without the "-lrt". $ g++ -O2 -o sigcatcher -pthread sigcatcher.cpp $ g++ --version i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 (Apple Inc. build 5493) > Make sure optimization is enabled to ensure volatile is used where > it's > needed. Assuming everything works right you should get output like: > > $ ./sigcatcher > Hello, World! > Got a result of 1 > Exited thread > $ The next problem is, that sem_init(..) isn't implemented here. $ ./sigcatcher Error: sem_init: Function not implemented $ It seems that only named semaphores are implemented. I've changed this part of your code to use sem_open(..) instead [see attachment] and then I get the expected result: --Apple-Mail-5--655527130 Content-Disposition: attachment; filename=sigcatcher-sem_open.cpp Content-Type: application/octet-stream; x-unix-mode=0644; name="sigcatcher-sem_open.cpp" Content-Transfer-Encoding: quoted-printable /*=0A=20*=20Copyright=20=C2=A9=202011=20Michael=20Pyne=20=0A= =20*=0A=20*=20This=20library=20is=20free=20software;=20you=20can=20= redistribute=20it=20and/or=0A=20*=20modify=20it=20under=20the=20terms=20= of=20the=20GNU=20Library=20General=20Public=0A=20*=20License=20version=20= 2=20as=20published=20by=20the=20Free=20Software=20Foundation.=0A=20*=0A=20= *=20This=20library=20is=20distributed=20in=20the=20hope=20that=20it=20= will=20be=20useful,=0A=20*=20but=20WITHOUT=20ANY=20WARRANTY;=20without=20= even=20the=20implied=20warranty=20of=0A=20*=20MERCHANTABILITY=20or=20= FITNESS=20FOR=20A=20PARTICULAR=20PURPOSE.=20=20See=20the=20GNU=0A=20*=20= Library=20General=20Public=20License=20for=20more=20details.=0A=20*=0A=20= *=20You=20should=20have=20received=20a=20copy=20of=20the=20GNU=20Library=20= General=20Public=20License=0A=20*=20along=20with=20this=20library;=20see=20= the=20file=20COPYING.LIB.=20=20If=20not,=20write=20to=0A=20*=20the=20= Free=20Software=20Foundation,=20Inc.,=2051=20Franklin=20Street,=20Fifth=20= Floor,=0A=20*=20Boston,=20MA=2002110-1301,=20USA.=0A=20*/=0A=0A#include=20= =0A=0A#include=20=0A#include=20=0A#include=20= =0A#include=20=0A#include=20=0A= #include=20=0A#include=20=0A#include=20=0A=0A= class=20KSDCOperation=0A{=0Apublic:=0A=20=20=20=20virtual=20= ~KSDCOperation();=0A=20=20=20=20virtual=20void=20operator()()=20=3D=200;=0A= };=0A=0AKSDCOperation::~KSDCOperation()=0A{=0A}=0A=0Astruct=20= SigCatcherSharedData=0A{=0A=20=20=20=20sem_t*=20workSemaphore;=0A=20=20=20= =20volatile=20int=20keepLooping;=0A=20=20=20=20volatile=20bool=20= resultValid;=0A=20=20=20=20volatile=20sig_atomic_t=20resultLock;=0A=0A=20= =20=20=20KSDCOperation=20*operation;=0A};=0A=0Astruct=20= SigCatcherSignalHandlerData=0A{=0A=20=20=20=20sigjmp_buf=20env;=0A};=0A=0A= pthread_key_t=20gSigThreadKey;=0A=0Astatic=20void=20= memoryFaultHandler(int=20signal)=0A{=0A=20=20=20=20std::cout=20<<=20= "Hello=20from=20sig=20handler."=20<<=20std::endl;=0A=0A=20=20=20=20//=20= Figure=20out=20what=20KSDC=20object=20we=20need=20to=20jump=20back=20to.=0A= =20=20=20=20SigCatcherSignalHandlerData=20*localData=20=3D=20= reinterpret_cast(=0A=20=20=20=20=20=20=20= =20pthread_getspecific(gSigThreadKey)=0A=20=20=20=20);=0A=0A=20=20=20=20= //=20Nothing=20to=20do=20now=20but=20jump=20to=20our=20pre-arranged=20= error=20handler.=0A=20=20=20=20siglongjmp(localData->env,=20signal);=0A}=0A= =0Avoid*=20signalCatcherThread(void=20*in)=0A{=0A=20=20=20=20= SigCatcherSharedData=20*shared=20=3D=20= reinterpret_cast(in);=0A=0A=20=20=20=20//=20= Store=20the=20information=20needed=20for=20our=20thread's=20signal=20= handler=20now.=0A=20=20=20=20pthread_key_create(&gSigThreadKey,=20free);=0A= =0A=20=20=20=20SigCatcherSignalHandlerData=20*localData=20=3D=20new=20= SigCatcherSignalHandlerData;=0A=20=20=20=20= pthread_setspecific(gSigThreadKey,=20localData);=0A=0A=20=20=20=20//=20= Set=20the=20signals=20we'll=20handle=0A=20=20=20=20sigset_t=20= handledSignals;=0A=0A=20=20=20=20//=20Block=20all=20signals=0A=20=20=20=20= sigfillset(&handledSignals);=0A=0A=20=20=20=20//=20Except=20these...=0A=20= =20=20=20sigdelset(&handledSignals,=20SIGSEGV);=0A=20=20=20=20= sigdelset(&handledSignals,=20SIGBUS);=0A=20=20=20=20= sigdelset(&handledSignals,=20SIGFPE);=0A=20=20=20=20= sigdelset(&handledSignals,=20SIGILL);=0A=0A=20=20=20=20int=20err;=0A=20=20= =20=20if=20((err=20=3D=20pthread_sigmask(SIG_SETMASK,=20&handledSignals,=20= 0))=20!=3D=200)=20{=0A=20=20=20=20=20=20=20=20std::cerr=20<<=20"error:=20= pthread_sigmask:=20"=20<<=20strerror(err)=20<<=20std::endl;=0A=20=20=20=20= }=0A=0A=20=20=20=20//=20Now=20establish=20handlers=20for=20signals=20= that=20are=20not=20blocked=0A=20=20=20=20struct=20sigaction=20= sigHandler;=0A=0A=20=20=20=20sigHandler.sa_handler=20=3D=20= memoryFaultHandler;=0A=20=20=20=20sigemptyset(&sigHandler.sa_mask);=0A=20= =20=20=20sigHandler.sa_flags=20=3D=200;=0A=0A=20=20=20=20if=20((err=20=3D=20= sigaction(SIGSEGV,=20&sigHandler,=200))=20<=200)=20{=0A=20=20=20=20=20=20= =20=20std::cerr=20<<=20"Error:=20sigaction:=20"=20<<=20strerror(err)=20= <<=20std::endl;=0A=20=20=20=20}=0A=20=20=20=20if=20((err=20=3D=20= sigaction(SIGBUS,=20&sigHandler,=200))=20<=200)=20{=0A=20=20=20=20=20=20=20= =20std::cerr=20<<=20"Error:=20sigaction:=20"=20<<=20strerror(err)=20<<=20= std::endl;=0A=20=20=20=20}=0A=20=20=20=20if=20((err=20=3D=20= sigaction(SIGFPE,=20&sigHandler,=200))=20<=200)=20{=0A=20=20=20=20=20=20=20= =20std::cerr=20<<=20"Error:=20sigaction:=20"=20<<=20strerror(err)=20<<=20= std::endl;=0A=20=20=20=20}=0A=20=20=20=20if=20((err=20=3D=20= sigaction(SIGILL,=20&sigHandler,=200))=20<=200)=20{=0A=20=20=20=20=20=20=20= =20std::cerr=20<<=20"Error:=20sigaction:=20"=20<<=20strerror(err)=20<<=20= std::endl;=0A=20=20=20=20}=0A=0A=20=20=20=20int=20jmpResult=20=3D=20= sigsetjmp(localData->env,=201);=0A=20=20=20=20if=20(jmpResult)=20{=0A=20=20= =20=20=20=20=20=20//=20siglongjmp=20called=0A=20=20=20=20=20=20=20=20= std::cerr=20<<=20"Caught=20signal:=20"=20<<=20jmpResult=20<<=20= std::endl;=0A=0A=20=20=20=20=20=20=20=20//=20Mark=20whatever=20operation=20= was=20going=20on=20as=20failed.=0A=20=20=20=20=20=20=20=20= shared->resultValid=20=3D=20false;=0A=0A=20=20=20=20=20=20=20=20//=20= Ensure=20we=20unlock=20our=20shared=20data=20if=20we=20had=20it=20locked=20= before.=0A=20=20=20=20=20=20=20=20shared->resultLock=20=3D=200;=0A=20=20=20= =20=20=20=20=20pthread_exit(0);=0A=20=20=20=20}=0A=20=20=20=20else=20{=0A= =20=20=20=20=20=20=20=20//=20jmpbuf=20set,=20continue=20as=20normal=0A=20= =20=20=20=20=20=20=20shared->resultValid=20=3D=20true;=0A=0A=20=20=20=20=20= =20=20=20while=20(shared->keepLooping)=20{=0A=20=20=20=20=20=20=20=20=20=20= =20=20while=20(sem_wait(shared->workSemaphore)=20!=3D=200)=20{=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20if=20(errno=20!=3D=20EINTR)=20{=0A= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20err=20=3D=20= errno;=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= std::cerr=20<<=20"Error:=20sem_wait:=20"=20<<=20strerror(err)=20<<=20= std::endl;=0A=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= shared->resultValid=20=3D=20false;=0A=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20shared->resultLock=20=3D=200;=0A=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20pthread_exit(0);=0A=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20}=0A=20=20=20=20=20=20=20=20=20=20=20= =20}=0A=0A=20=20=20=20=20=20=20=20=20=20=20=20//=20This=20should=20only=20= happen=20if=20the=20parent=20thread=20has=20told=20us=20to=0A=20=20=20=20= =20=20=20=20=20=20=20=20//=20exit.=0A=20=20=20=20=20=20=20=20=20=20=20=20= if=20(!shared->keepLooping)=20{=0A=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20pthread_exit(0);=0A=20=20=20=20=20=20=20=20=20=20=20=20}=0A=0A=20= =20=20=20=20=20=20=20=20=20=20=20//=20Actually=20do=20the=20freakin'=20= work=0A=20=20=20=20=20=20=20=20=20=20=20=20(*shared->operation)();=0A=0A=20= =20=20=20=20=20=20=20=20=20=20=20//=20Uncomment=20one=20of=20these=20to=20= simulate=20a=20crash.=0A=20=20=20=20=20=20=20=20=20=20=20=20= //*(reinterpret_cast(0))=20=3D=205;=0A=20=20=20=20=20=20=20=20=20=20= =20=20//volatile=20int=20dummy=20=3D=201/0;=0A=0A=20=20=20=20=20=20=20=20= =20=20=20=20//=20Free=20up=20out=20parent=20thread=20currently=20= spinning.=0A=20=20=20=20=20=20=20=20=20=20=20=20shared->resultLock=20=3D=20= 0;=0A=20=20=20=20=20=20=20=20}=0A=20=20=20=20}=0A=0A=20=20=20=20return=20= 0;=0A}=0A=0Aclass=20HelloOperation=20:=20public=20KSDCOperation=0A{=0A= public:=0A=20=20=20=20HelloOperation()=20:=20KSDCOperation(),=20= m_done(false)=0A=20=20=20=20{=0A=20=20=20=20}=0A=0A=20=20=20=20virtual=20= void=20operator()()=0A=20=20=20=20{=0A=20=20=20=20=20=20=20=20std::cout=20= <<=20"Hello,=20World!"=20<<=20std::endl;=0A=20=20=20=20=20=20=20=20= m_done=20=3D=20true;=20//=20Result=0A=20=20=20=20}=0A=0A=20=20=20=20//=20= Just=20to=20show=20how=20results=20would=20have=20to=20be=20stored=20in=20= the=20functor=20object=0A=20=20=20=20//=20itself.=0A=20=20=20=20bool=20= m_done;=0A};=0A=0Aint=20main()=0A{=0A=20=20=20=20SigCatcherSharedData=20= sharedData;=0A=20=20=20=20sharedData.keepLooping=20=3D=20true;=0A=20=20=20= =20sharedData.resultValid=20=3D=20true;=0A=20=20=20=20= sharedData.operation=20=3D=200;=0A=0A=20=20=20=20int=20err;=0A=20=20=20=20= sem_t*=20sem=20=3D=20sem_open("sharedData.workSemaphore",=20O_CREAT,=20=20= 0777,=200);=0A=20=20=20=20if=20(sem=20=3D=3D=20SEM_FAILED)=20{=0A=20=20=20= =20=20=20=20=20err=20=3D=20errno;=0A=20=20=20=20=20=20=20=20std::cerr=20= <<=20"Error:=20sem_init:=20"=20<<=20strerror(err)=20<<=20std::endl;=0A=20= =20=20=20=20=20=20=20exit(1);=0A=20=20=20=20}=0A=20=20=20=20else=20{=0A=20= =20=20=20=20=20=20=20sharedData.workSemaphore=20=3D=20sem;=0A=20=20=20=20= }=0A=0A=20=20=20=20pthread_t=20exeThread;=0A=20=20=20=20if=20((err=20=3D=20= pthread_create(&exeThread,=200,=20signalCatcherThread,=20&sharedData))=20= <=200)=20{=0A=20=20=20=20=20=20=20=20std::cerr=20<<=20"Error:=20= pthread_create:=20"=20<<=20strerror(err)=20<<=20std::endl;=0A=20=20=20=20= =20=20=20=20exit(1);=0A=20=20=20=20}=0A=0A=20=20=20=20//=20For=20each=20= task=20to=20complete,=20we=20need=20to=20have=20a=20KSDCOperation=20= object,=20and=0A=20=20=20=20//=20get=20our=20spinlock=20ready=20by=20= calling=20ref.=20Then=20we=20post=20to=20the=20workSemaphore=0A=20=20=20=20= //=20to=20free=20our=20work=20thread=20and=20spin=20on=20resultLock.=20= We=20must=20ALWAYS=20check=20the=0A=20=20=20=20//=20validity=20of=20the=20= result=20however.=20If=20invalid=20the=20thread=20has=20terminated,=0A=20= =20=20=20//=20though=20we=20can=20re-create=20and=20try=20again.=0A=20=20= =20=20sharedData.resultLock=20=3D=201;=0A=20=20=20=20HelloOperation=20= *op=20=3D=20new=20HelloOperation;=0A=20=20=20=20sharedData.operation=20=3D= =20op;=0A=0A=20=20=20=20sem_post(sharedData.workSemaphore);=0A=20=20=20=20= while(sharedData.resultLock)=0A=20=20=20=20=20=20=20=20;=0A=0A=20=20=20=20= if(sharedData.resultValid)=20{=0A=20=20=20=20=20=20=20=20std::cout=20<<=20= "Got=20a=20result=20of=20"=20<<=20op->m_done=20<<=20std::endl;=0A=20=20=20= =20}=0A=20=20=20=20else=20{=0A=20=20=20=20=20=20=20=20std::cerr=20<<=20= "WHOA,=20something=20happened!=20:(\n";=0A=20=20=20=20=20=20=20=20= pthread_join(exeThread,=200);=0A=20=20=20=20=20=20=20=20exit(1);=0A=20=20= =20=20}=0A=0A=20=20=20=20//=20Normal=20termination.=20No=20need=20to=20= use=20resultLock=20spinlock=20here.=0A=0A=20=20=20=20= sharedData.keepLooping=20=3D=20false;=0A=20=20=20=20= sem_post(sharedData.workSemaphore);=0A=20=20=20=20= pthread_join(exeThread,=200);=0A=20=20=20=20delete=20= sharedData.operation;=0A=20=20=20=20if=20= (sem_close(sharedData.workSemaphore)=20<=200)=20{=0A=20=20=20=20=20=20=20= =20err=20=3D=20errno;=0A=20=20=20=20=20=20=20=20std::cerr=20<<=20"Error:=20= sem_close:=20"=20<<=20strerror(err)=20<<=20std::endl;=0A=20=20=20=20=20=20= =20=20exit(1);=0A=20=20=20=20}=0A=0A=20=20=20=20std::cout=20<<=20"Exited=20= thread\n";=0A=0A=20=20=20=20return=200;=0A}=0A= --Apple-Mail-5--655527130 Content-Type: text/plain; charset=US-ASCII; format=flowed; delsp=yes Content-Transfer-Encoding: 7bit $ g++ -O2 -o sigcatcher-sem_open -pthread sigcatcher-sem_open.cpp $ ./sigcatcher-sem_open Hello, World! Got a result of 1 Exited thread $ bye, Jonas > > If you want to see the signal handler in action there's a couple of > lines you > can uncomment (just grep for uncomment to find where). > > Obviously any other feedback on possible issues is appreciated as > well, but > basically I'd like to catch any portability issues early this time > instead of > after-the-fact. > > Please CC me on any replies as I'm not subscribed. > > Regards, > - Michael > Pyne_______________________________________________ > kde-mac@kde.org > List Information: https://mail.kde.org/mailman/listinfo/kde-mac > KDE/Mac Information: http://techbase.kde.org/index.php?title=Projects/KDE_on_Mac_OS_X --Apple-Mail-5--655527130 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kde-mac@kde.org List Information: https://mail.kde.org/mailman/listinfo/kde-mac KDE/Mac Information: http://techbase.kde.org/index.php?title=Projects/KDE_on_Mac_OS_X --Apple-Mail-5--655527130--