u_result u_dispatcherInsertListener( u_dispatcher _this, u_dispatcherListener listener, c_voidp userData) { u_listener ul; os_threadAttr attr; v_observer ke; u_result result = U_RESULT_OK; c_char *name; if ((_this != NULL) && (listener != NULL)) { os_mutexLock(&_this->mutex); ul = u_listenerNew(listener,userData); _this->listeners = c_iterInsert(_this->listeners,ul); if (os_threadIdToInteger(_this->threadId) == 0U) { result = u_entityReadClaim(u_entity(_this), (v_entity*)(&ke)); if(result == U_RESULT_OK) { assert(ke); name = v_entityName(ke); if (name == NULL) { name = "NoName"; } os_threadAttrInit(&attr); os_threadCreate(&_this->threadId, name, &attr,dispatch, (void *)_this); result = u_entityRelease(u_entity(_this)); if (result != U_RESULT_OK) { OS_REPORT(OS_ERROR, "u_dispatcherInsertListener", 0, "Release observer failed."); } } else { OS_REPORT(OS_WARNING, "u_dispatcherInsertListener", 0, "Failed to claim Dispatcher."); } } u_entityEnable(u_entity(_this)); os_mutexUnlock(&_this->mutex); } else { OS_REPORT(OS_ERROR,"u_dispatcherInsertListener",0, "Illegal parameter."); result = U_RESULT_ILL_PARAM; } return result; }
d_groupCreationQueue d_groupCreationQueueNew( d_admin admin) { d_groupCreationQueue queue; os_result osr; os_threadAttr attr; assert(admin); queue = d_groupCreationQueue(os_malloc(C_SIZEOF(d_groupCreationQueue))); if(queue) { d_lockInit(d_lock(queue), D_GROUP_CREATION_QUEUE, d_groupCreationQueueDeinit); if(queue) { queue->groups = c_iterNew(NULL); queue->terminate = FALSE; queue->admin = admin; queue->groupsToCreateVolatile = 0; queue->groupsToCreateTransient = 0; queue->groupsToCreatePersistent = 0; osr = os_threadAttrInit(&attr); if(osr == os_resultSuccess) { osr = os_threadCreate(&queue->actionThread, "groupCreationThread", &attr, (void*(*)(void*))d_groupCreationQueueRun, (void*)queue); if(osr != os_resultSuccess) { d_groupCreationQueueFree(queue); queue = NULL; } } else { d_groupCreationQueueFree(queue); queue = NULL; } } } return queue; }
/* See header-file for */ unsigned int DDS::DataReader_impl::set_ParallelReadThreadCount( unsigned int value ) { DDS::ReturnCode_t exc = DDS::RETCODE_OK; if(os_mutexLock(&dr_mutex) != os_resultSuccess) { OS_REPORT(OS_FATAL, "CCPP", 0, "Failed to claim mutex"); exc = DDS::RETCODE_ERROR; goto fatal_mtx; } if(pdc){ /* Signal eventual current threads to shutdown */ pdc_terminateWorkers(pdc); /* Join threads */ pdc_joinWorkers(workers, nrofWorkers); /* Assert that all threads are actually stopped, so the terminate flag is * reset (last one to stop will do this). */ assert(pdc->terminate == 0); delete workers; workers = NULL; /* If the requested size is 0 or 1, this will both result in a single-threaded * copy, so we don't have to start any extra threads. If previously there * were threads created, we can now cleanup the context as well. */ if(value <= 1){ delete pdc; pdc = NULL; } } if(value > 1){ if(!pdc){ /* Create a parallelDemarshalling context. */ try{ if((pdc = new ccpp_parDemContext()) == NULL) { exc = DDS::RETCODE_OUT_OF_RESOURCES; goto err_out_of_resources; } } catch (::DDS::ReturnCode_t e){ exc = e; goto err_out_of_resources; } } os_threadAttr thrAttrs; os_result result; if((result = os_threadAttrInit(&thrAttrs)) != os_resultSuccess){ exc = DDS::RETCODE_ERROR; goto err_thr_attrs; } if((workers = new os_threadId[value - 1]) == NULL){ exc = DDS::RETCODE_OUT_OF_RESOURCES; goto err_workers_alloc; } assert(pdcMainFnc); assert(nrofWorkers == 0); for(nrofWorkers = 0; nrofWorkers < (value - 1); nrofWorkers++){ result = os_threadCreate( &workers[nrofWorkers], "parDemWorker", /* TODO: pretty name */ &thrAttrs, pdcMainFnc, (void*)pdc); if(result != os_resultSuccess){ nrofWorkers--; /* If a thread was started (nrofWorkers > 0), then something * happened and we warn that not all threads could be started * (probably due to out of resources condition). * If no threads were started at all, an error occurred. */ OS_REPORT_2(nrofWorkers ? OS_WARNING : OS_ERROR, "CCPP", result, "Starting a parallel demarshalling worker thread failed; %d out of %d requested threads are available for parallel demarshalling.", nrofWorkers + 1, value); if(nrofWorkers == 0) { exc = DDS::RETCODE_ERROR; goto err_thread_start; } else { break; } } } } os_mutexUnlock(&dr_mutex); /* When a ParallelReadThreadCount of x is requested only x - 1 threads are * started, since the application thread is performing read actions as well */ return nrofWorkers + 1; /* Error handling */ err_thread_start: err_workers_alloc: err_thr_attrs: err_out_of_resources: os_mutexUnlock(&dr_mutex); fatal_mtx: assert(exc != DDS::RETCODE_OK); throw exc; }
static u_result startMonitoring( const u_participant participant, const u_waitset waitset, const struct builtin_datareader_set *drset) { c_iter events, topics; u_waitsetEvent event; c_time timeout; os_uint32 reportInterval; v_gid participantGid, publicationGid, subscriptionGid, gid; u_result result; u_dataReader dataReader; u_topic topic; c_iter vgroups; v_group vgroup; v_duration duration; c_long participantOffset, publicationOffset, subscriptionOffset; os_threadAttr attr; os_result osr; /*Resolve unique identifications of readers*/ participantGid = u_entityGid((u_entity)drset->participant_dr); publicationGid = u_entityGid((u_entity)drset->publication_dr); subscriptionGid = u_entityGid((u_entity)drset->subscription_dr); /*Resolve topics to find offsets in the data. The offsets are used later on*/ duration.seconds = 0; duration.nanoseconds = 0; topics = u_participantFindTopic(participant, V_PARTICIPANTINFO_NAME, duration); topic = c_iterTakeFirst(topics); if(topic){ result = u_entityAction(u_entity(topic), resolveOffset, &participantOffset); } else { result = U_RESULT_INTERNAL_ERROR; in_printf(IN_LEVEL_SEVERE, "Could not resolve participant info offset.\n"); } c_iterFree(topics); if(result == U_RESULT_OK){ topics = u_participantFindTopic(participant, V_PUBLICATIONINFO_NAME, duration); topic = c_iterTakeFirst(topics); if(topic){ result = u_entityAction(u_entity(topic), resolveOffset, &publicationOffset); } else { result = U_RESULT_INTERNAL_ERROR; in_printf(IN_LEVEL_SEVERE, "Could not resolve publication info offset.\n"); } c_iterFree(topics); } if(result == U_RESULT_OK){ topics = u_participantFindTopic(participant, V_SUBSCRIPTIONINFO_NAME, duration); topic = c_iterTakeFirst(topics); if(topic){ result = u_entityAction(u_entity(topic), resolveOffset, &subscriptionOffset); } else { result = U_RESULT_INTERNAL_ERROR; in_printf(IN_LEVEL_SEVERE, "Could not resolve subscription info offset.\n"); } c_iterFree(topics); } if(result == U_RESULT_OK){ timeout.seconds = 0; timeout.nanoseconds = 100 * 1000 * 1000; /*100 ms*/ in_printf(IN_LEVEL_FINE, "Collecting initial entities...\n"); result = handleParticipant(drset->participant_dr, participantOffset); if(result == U_RESULT_OK){ result = handlePublication(drset->publication_dr, publicationOffset, drset->participant_dr, participantOffset); if(result == U_RESULT_OK){ result = handleSubscription(drset->subscription_dr, subscriptionOffset, drset->participant_dr, participantOffset); if(result == U_RESULT_OK){ vgroups = v_serviceTakeNewGroups(service); vgroup = (v_group)c_iterTakeFirst(vgroups); while(vgroup && result == U_RESULT_OK){ result = handleGroup(service, vgroup); c_free(vgroup); vgroup = (v_group)c_iterTakeFirst(vgroups); } c_iterFree(vgroups); if(result == U_RESULT_OK){ in_printf(IN_LEVEL_FINE, "Waiting for entities to be created/deleted...\n"); } else { in_printf(IN_LEVEL_SEVERE, "Could not collect initial groups...\n"); } } else { in_printf(IN_LEVEL_SEVERE, "Could not collect initial subscriptions...\n"); } } else { in_printf(IN_LEVEL_SEVERE, "Could not collect initial publications...\n"); } } else { in_printf(IN_LEVEL_SEVERE, "Could not collect initial participants...\n"); } } osr = os_threadAttrInit(&attr); if(osr == os_resultSuccess){ osr = os_threadCreate(&clientWriterThread, "clientWriterMonitor", &attr, in_discoveryClientWriterMonitor, NULL); if(osr != os_resultSuccess){ result = U_RESULT_INTERNAL_ERROR; } } else { result = U_RESULT_INTERNAL_ERROR; } reportInterval = 0; while(result == U_RESULT_OK && !terminate){ events = NULL; /*Wait for events to occur*/ result = u_waitsetTimedWaitEvents(waitset, timeout, &events); if(result == U_RESULT_OK){ event = (u_waitsetEvent)(c_iterTakeFirst(events)); while(event){ if(((event->events) & V_EVENT_DATA_AVAILABLE) == V_EVENT_DATA_AVAILABLE) { if(event->entity){ dataReader = (u_dataReader)event->entity; gid = u_entityGid(event->entity); if(v_gidCompare(gid, participantGid) == C_EQ){ result = handleParticipant( drset->participant_dr, participantOffset); } else if(v_gidCompare(gid, subscriptionGid) == C_EQ){ result = handleSubscription( drset->subscription_dr, subscriptionOffset, drset->participant_dr, participantOffset); } else if(v_gidCompare(gid, publicationGid) == C_EQ){ result = handlePublication( drset->publication_dr, publicationOffset, drset->participant_dr, participantOffset); } else { in_printf(IN_LEVEL_SEVERE, "This is impossible...at least in my understanding of the world.\n"); result = U_RESULT_INTERNAL_ERROR; } } else { in_printf(IN_LEVEL_WARNING, "DATA_AVAILABLE (%d) but no entity.\n", event->events); } } else if(((event->events) & V_EVENT_NEW_GROUP) == V_EVENT_NEW_GROUP) { vgroups = v_serviceTakeNewGroups(service); vgroup = (v_group)c_iterTakeFirst(vgroups); while(vgroup && result == U_RESULT_OK){ result = handleGroup(service, vgroup); c_free(vgroup); vgroup = (v_group)c_iterTakeFirst(vgroups); } c_iterFree(vgroups); } else { in_printf(IN_LEVEL_SEVERE, "Received unexpected event %d.\n", event->events); result = U_RESULT_INTERNAL_ERROR; } u_waitsetEventFree(event); event = (u_waitsetEvent)(c_iterTakeFirst(events)); } } else if(result == U_RESULT_DETACHING){ in_printf(IN_LEVEL_INFO, "Starting termination now...\n"); } else if(result == U_RESULT_TIMEOUT){ result = U_RESULT_OK; } else { in_printf(IN_LEVEL_SEVERE, "Waitset wait failed.\n"); } if(events){/* events may be null if waitset was deleted */ c_iterFree(events); } reportInterval++; if(reportInterval >= 5){ /*reportEntities();*/ reportInterval = 0; } } return result; }
c_bool d_waitsetAttach( d_waitset waitset, d_waitsetEntity we) { c_bool result = FALSE; u_result ur; os_result osr; d_waitsetHelper helper; c_ulong mask; d_admin admin; d_durability durability; assert(d_objectIsValid(d_object(waitset), D_WAITSET) == TRUE); assert(d_objectIsValid(d_object(we), D_WAITSET_ENTITY) == TRUE); if(waitset && we){ d_lockLock(d_lock(waitset)); if(!we->waitset) { if(c_iterContains(waitset->entities, we) == FALSE) { waitset->entities = c_iterInsert(waitset->entities, we); if(waitset->runToCompletion == TRUE){ ur = u_waitsetAttach(waitset->uwaitset, u_entity(we->dispatcher), (c_voidp)we->dispatcher); if(ur == U_RESULT_OK) { we->waitset = waitset; result = TRUE; } } else { admin = d_subscriberGetAdmin(waitset->subscriber); durability = d_adminGetDurability(admin); helper = os_malloc(C_SIZEOF(d_waitsetHelper)); helper->waitset = waitset; helper->entity = we; helper->terminate = FALSE; helper->tid = OS_THREAD_ID_NONE; helper->userWaitset = u_waitsetNew(u_participant(d_durabilityGetService(durability))); mask = V_EVENT_DATA_AVAILABLE; mask |= V_EVENT_NEW_GROUP; mask |= V_EVENT_HISTORY_DELETE; mask |= V_EVENT_HISTORY_REQUEST; mask |= V_EVENT_PERSISTENT_SNAPSHOT; mask |= V_EVENT_TRIGGER; u_waitsetSetEventMask(helper->userWaitset, mask); ur = u_waitsetAttach(helper->userWaitset, u_entity(we->dispatcher), (c_voidp)we->dispatcher); if(ur != U_RESULT_OK) { assert(FALSE); } else { result = TRUE; } if(result){ waitset->threads = c_iterInsert(waitset->threads, helper); osr = os_threadCreate(&(helper->tid), we->name, &(we->attr), d_waitsetEventHandler, helper); if(osr != os_resultSuccess){ c_iterTake(waitset->threads, helper); u_waitsetDetach(helper->userWaitset, u_entity(we->dispatcher)); u_waitsetFree(helper->userWaitset); os_free(helper); result = FALSE; } } else { u_waitsetFree(helper->userWaitset); os_free(helper); } } } } d_lockUnlock(d_lock(waitset)); } return result; }
d_waitset d_waitsetNew( d_subscriber subscriber, c_bool runToCompletion, c_bool timedWait) { d_durability durability; d_admin admin; u_participant uparticipant; os_threadAttr attr; os_result osr; c_ulong mask; d_waitset waitset = NULL; assert(d_objectIsValid(d_object(subscriber), D_SUBSCRIBER) == TRUE); if(subscriber){ waitset = d_waitset(os_malloc(C_SIZEOF(d_waitset))); if(waitset) { d_lockInit(d_lock(waitset), D_WAITSET, d_waitsetDeinit); admin = d_subscriberGetAdmin(subscriber); durability = d_adminGetDurability(admin); uparticipant = u_participant(d_durabilityGetService(durability)); waitset->terminate = FALSE; waitset->subscriber = subscriber; waitset->entities = c_iterNew(NULL); waitset->runToCompletion = runToCompletion; waitset->timedWait = timedWait; if(runToCompletion == TRUE){ waitset->uwaitset = u_waitsetNew(uparticipant); mask = V_EVENT_DATA_AVAILABLE; mask |= V_EVENT_NEW_GROUP; mask |= V_EVENT_HISTORY_DELETE; mask |= V_EVENT_HISTORY_REQUEST; mask |= V_EVENT_PERSISTENT_SNAPSHOT; mask |= V_EVENT_TRIGGER; u_waitsetSetEventMask(waitset->uwaitset, mask); osr = os_threadAttrInit(&attr); if(osr == os_resultSuccess) { osr = os_threadCreate(&waitset->thread, "waitsetThread", &attr, d_waitsetEventHandlerRunToCompletion, waitset); } if(osr != os_resultSuccess) { d_waitsetFree(waitset); } waitset->threads = NULL; } else { waitset->threads = c_iterNew(NULL); waitset->uwaitset = NULL; waitset->thread = OS_THREAD_ID_NONE; } } } return waitset; }
static os_result os_signalHandlerInit( os_signalHandler _this) { os_result result = os_resultSuccess; os_sigset block_all_sigset, old_sigset; unsigned i; int r; os_threadAttr thrAttr; assert(_this); _this->handleExceptions = OS_FALSE; if(os__signalHandlerCallbackInit(&_this->callbackInfo) != os_resultSuccess) { goto err_callbackInfoInit; } if(!isSignallingSafe(1)){ return os_resultSuccess; } /* Initialise the exceptionsMask */ sigemptyset(&exceptionsMask); for(i = 0; i < lengthof(exceptions); i++){ sigaddset(&exceptionsMask, exceptions[i]); } /* Initialise the quitsMask */ sigemptyset(&quitsMask); for(i = 0; i < quits_len; i++){ sigaddset(&quitsMask, quits[i]); } /* create signal handling pipes */ r = pipe(_this->pipeIn); if (r < 0) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "pipe(_this->pipeIn) failed, result = %d", r); goto err_pipeIn; } r = fcntl(_this->pipeIn[0], F_SETFD, 1); if (r < 0) { OS_REPORT(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeIn[0]) failed, result = %d", r); goto err_pipeInFcntl; } r = fcntl(_this->pipeIn[1], F_SETFD, 1); if (r < 0) { OS_REPORT(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeIn[1]) failed, result = %d", r); goto err_pipeInFcntl; } r = pipe(_this->pipeOut); if (r < 0) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 1, "pipe(_this->pipeOut) failed, result = %d", r); goto err_pipeOut; } r = fcntl(_this->pipeOut[0], F_SETFD, 1); if (r < 0) { OS_REPORT(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeOut[0]) failed, result = %d", r); goto err_pipeOutFcntl; } r = fcntl(_this->pipeOut[1], F_SETFD, 1); if (r < 0) { OS_REPORT(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeOut[1]) failed, result = %d", r); goto err_pipeOutFcntl; } /* Block all signals in order to start the signalHandlerThread with all * signals blocked. */ result = os_sigsetFill(&block_all_sigset); if (result != os_resultSuccess) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "os_sigsetFill(&block_all_sigset) failed: %s", os_resultImage(result)); goto err_sigsetMask; } /* Remove signals that cannot be blocked. */ for (i = 0; i < lengthof(excludes); i++) { const int sig = excludes[i]; if (os_sigsetDel(&block_all_sigset, sig) != 0) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "os_sigsetDel(0x%"PA_PRIxADDR", %d) failed, result = %d", (os_address)&_this->action, sig, r); goto err_sigsetMask; } } result = os_sigThreadSetMask(&block_all_sigset, &old_sigset); if (result != os_resultSuccess) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "os_sigThreadSetMask(0x%"PA_PRIxADDR", 0x%"PA_PRIxADDR") failed: %s", (os_address)&block_all_sigset, (os_address)&old_sigset, os_resultImage(result)); goto err_sigsetMask; } /* Setup signal handler thread. */ os_threadAttrInit(&thrAttr); thrAttr.stackSize = 4*1024*1024; /* 4 MB */ result = os_threadCreate(&_this->threadId, "signalHandler", &thrAttr, signalHandlerThread, (void*)_this); if (result != os_resultSuccess) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "os_threadCreate(0x%"PA_PRIxADDR", 0x%"PA_PRIxADDR",0x%"PA_PRIxADDR",0) failed: %s", (os_address)&_this->threadId, (os_address)&thrAttr, (os_address)signalHandlerThread, os_resultImage(result)); goto err_threadCreate; } /* Reset signal mask to original value. */ result = os_sigThreadSetMask(&old_sigset, NULL); if (result != os_resultSuccess) { OS_REPORT(OS_ERROR, "os_signalHandlerInit", 0, "os_sigThreadSetMask(0x%"PA_PRIxADDR", NULL) failed: %s", (os_address)&old_sigset, os_resultImage(result)); goto err_sigResetMask; } /* install signal handlers */ _this->action = os_sigactionNew(signalHandler, &block_all_sigset, SA_SIGINFO); if (os_signalHandlerEnableExitSignals() != os_resultSuccess) { goto err_enableExitHandling; } return os_resultSuccess; /* Error handling */ err_enableExitHandling: err_sigResetMask: os__signalHandlerThreadStop(_this); err_threadCreate: (void) os_sigThreadSetMask(&old_sigset, NULL); err_sigsetMask: /* No undo needed for fcntl's/sigsetFill */ err_pipeOutFcntl: (void) close(_this->pipeOut[0]); (void) close(_this->pipeOut[1]); err_pipeOut: /* No undo needed for fcntl's */ err_pipeInFcntl: (void) close(_this->pipeIn[0]); (void) close(_this->pipeIn[1]); err_pipeIn: os__signalHandlerCallbackDeinit(&_this->callbackInfo); err_callbackInfoInit: return os_resultFail; }
/************************************************************** * Protected functions **************************************************************/ s_kernelManager s_kernelManagerNew( spliced daemon) { s_kernelManager km; s_configuration config; os_mutexAttr mtxAttr; os_condAttr cvAttr; int status; os_result osr; status = 0; km = os_malloc((os_uint32)C_SIZEOF(s_kernelManager)); if (km) { km->spliced = splicedGetService(daemon); km->active = 0; osr = os_mutexAttrInit(&mtxAttr); if (osr == os_resultSuccess) { mtxAttr.scopeAttr = OS_SCOPE_PRIVATE; osr = os_mutexInit(&km->mtx, &mtxAttr); } else { status++; } if (osr == os_resultSuccess) { osr = os_condAttrInit(&cvAttr); if (osr == os_resultSuccess) { cvAttr.scopeAttr = OS_SCOPE_PRIVATE; osr = os_condInit(&km->cv, &km->mtx, &cvAttr); } else { os_mutexDestroy(&km->mtx); /* don't care if this succeeds, already in error situation */ status++; } if (osr == os_resultSuccess) { config = splicedGetConfiguration(daemon); osr = os_threadCreate(&km->id, S_THREAD_KERNELMANAGER, &config->kernelManagerScheduling, kernelManager, km); if (osr != os_resultSuccess) { /* don't care if the following statements succeeds, already in error situation */ os_mutexDestroy(&km->mtx); os_condDestroy(&km->cv); status++; } } if (osr == os_resultSuccess) { config = splicedGetConfiguration(daemon); osr = os_threadCreate(&km->resendManager, S_THREAD_RESENDMANAGER, &config->resendManagerScheduling, resendManager, km); if (osr != os_resultSuccess) { /* don't care if the following statements succeeds, already in error situation */ os_mutexDestroy(&km->mtx); os_condDestroy(&km->cv); status++; } } if (osr == os_resultSuccess ) { config = splicedGetConfiguration(daemon); if (config->enableCandMCommandThread ) { osr = os_threadCreate(&km->cAndMCommandManager, S_THREAD_C_AND_M_COMMANDMANAGER, &config->cAndMCommandScheduling, cAndMCommandManager, km); if (osr != os_resultSuccess) { /* don't care if the following statements succeeds, already in error situation */ os_mutexDestroy(&km->mtx); os_condDestroy(&km->cv); status++; } } } } else { status++; } } if (status && km) { os_free(km); km = NULL; } return km; }
static os_result os_signalHandlerInit( os_signalHandler _this) { os_result result = os_resultSuccess; os_sigaction action; os_sigset block_all_sigset, old_sigset; int i, r; if (_this == NULL) { result = os_resultFail; } _this->exitRequestCallback = (os_signalHandlerExitRequestCallback)0; _this->exceptionCallback = (os_signalHandlerExceptionCallback)0; if(isSignallingSafe(1)) { /* Initialise the exceptionsMask */ sigemptyset(&exceptionsMask); for(i = 0; i < lengthof(exceptions); i++) { sigaddset(&exceptionsMask, exceptions[i]); } /* Initialise the quitsMask */ sigemptyset(&quitsMask); for(i = 0; i < lengthof(quits); i++) { sigaddset(&quitsMask, quits[i]); } /* create signal handling pipes */ if (result == os_resultSuccess) { r = pipe(_this->pipeIn); if (r<0) { OS_REPORT_1(OS_ERROR, "os_signalHandlerInit", 0, "pipe(_this->pipeIn) failed, result = %d", r); result = os_resultFail; } else { r = fcntl(_this->pipeIn[0], F_SETFD, 1); if (r<0) { OS_REPORT_1(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeIn[0]) failed, result = %d", r); assert(OS_FALSE); } r = fcntl(_this->pipeIn[1], F_SETFD, 1); if (r<0) { OS_REPORT_1(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeIn[1]) failed, result = %d", r); assert(OS_FALSE); } } } if (result == os_resultSuccess) { r = pipe(_this->pipeOut); if (r<0) { OS_REPORT_1(OS_ERROR, "os_signalHandlerInit", 1, "pipe(_this->pipeOut) failed, result = %d", r); result = os_resultFail; } else { r = fcntl(_this->pipeOut[0], F_SETFD, 1); if (r<0) { OS_REPORT_1(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeOut[0]) failed, result = %d", r); assert(OS_FALSE); } r = fcntl(_this->pipeOut[1], F_SETFD, 1); if (r<0) { OS_REPORT_1(OS_WARNING, "os_signalHandlerInit", 0, "fcntl(_this->pipeOut[1]) failed, result = %d", r); assert(OS_FALSE); } } } /* Block all signals */ if (result == os_resultSuccess) { result = os_sigsetFill(&block_all_sigset); if (result != os_resultSuccess) { OS_REPORT_1(OS_ERROR, "os_signalHandlerInit", 0, "os_sigsetFill(&block_all_sigset) failed, result = %d", r); assert(OS_FALSE); } else { result = os_sigThreadSetMask(&block_all_sigset, &old_sigset); if (result != os_resultSuccess) { OS_REPORT_3(OS_ERROR, "os_signalHandlerInit", 0, "os_sigThreadSetMask(0x%x, 0x%x) failed, result = %d", &block_all_sigset, &old_sigset, r); assert(OS_FALSE); } } } /* Setup signal handler thread. */ if (result == os_resultSuccess) { os_threadAttr thrAttr; result = os_threadAttrInit(&thrAttr); if (result != os_resultSuccess) { OS_REPORT_2(OS_ERROR, "os_signalHandlerInit", 0, "pthread_attr_init(0x%x) failed, result = %d", &thrAttr, r); assert(OS_FALSE); } else { thrAttr.stackSize = 4*1024*1024; /* 4 MB */ result = os_threadCreate(&_this->threadId, "signalHandler", &thrAttr, signalHandlerThread, (void*)_this); if (result != os_resultSuccess) { OS_REPORT_4(OS_ERROR, "os_signalHandlerInit", 0, "os_threadCreate(0x%x, 0x%x,0x%x,0) failed, result = %d", &_this->threadId, &thrAttr, signalHandlerThread, result); assert(OS_FALSE); } } } /* Reset signal mask to original value. */ if (result == os_resultSuccess) { result = os_sigThreadSetMask(&old_sigset, NULL); if (result != os_resultSuccess) { OS_REPORT_2(OS_ERROR, "os_signalHandlerInit", 0, "os_sigThreadSetMask(0x%x, NULL) failed, result = %d", &old_sigset, r); result = os_resultFail; assert(OS_FALSE); } } /* install signal handlers */ if (result == os_resultSuccess) { os_sigset mask; /* block all signals during handling of a signal */ result = os_sigsetFill(&mask); if (result != os_resultSuccess) { OS_REPORT_2(OS_ERROR, "os_signalHandlerInit", 0, "os_sigsetFill(0x%x) failed, result = %d", &action.sa_mask, result); } else { action = os_sigactionNew(signalHandler, &mask, SA_SIGINFO); } if (result == os_resultSuccess) { for (i=0; i<lengthof(exceptions); i++) { const int sig = exceptions[i]; r = os_sigsetDel(&action.sa_mask, sig); if (r<0) { OS_REPORT_3(OS_ERROR, "os_signalHandlerInit", 0, "os_sigsetDel(0x%x, %d) failed, result = %d", &action, sig, r); result = os_resultFail; assert(OS_FALSE); } } } if (result == os_resultSuccess) { for (i=0; i<lengthof(exceptions); i++) { const int sig = exceptions[i]; /* For exceptions we always set our own signal handler, since * applications that cause an exception are not in a position * to ignore it. However, we will chain the old handler to our * own. */ r = os_sigactionSet(sig, &action, &old_signalHandler[sig]); if (r < 0) { OS_REPORT_4(OS_ERROR, "os_signalHandlerInit", 0, "os_sigactionSet(%d, 0x%x, 0x%x) failed, result = %d", sig, &action, &old_signalHandler[sig], r); result = os_resultFail; assert(OS_FALSE); } } } if (result == os_resultSuccess) { for (i=0; i<lengthof(quits); i++) { const int sig = quits[i]; /* By passing NULL we only retrieve the currently set handler. If * the signal should be ignored, we don't do anything. Otherwise we * chain the old handler to our own. * man-page of sigaction only states behaviour when new * action is non-NULL, but all known implementations act as * expected. That is: return the currently set signal-hand- * ler (and not the previous, as the man-pages state). * NOTE: Not MT-safe */ r = os_sigactionSet(sig, NULL, &old_signalHandler[sig]); if (r == 0) { if(old_signalHandler[sig].sa_handler != SIG_IGN) { /* We don't know if the oldHandler has been modified in the mean * time, since there is no way to make the signal handler reentrant. * It doesn't make sense to look for modifications now, since a * new modification could be on its way while we are processing * the current modification. * For that reason we will ignore any intermediate modifications * and continue setting our own handler. Processes should therefore * refrain from modifying the signal handler in multiple threads. */ r = os_sigactionSet(sig, &action, NULL); if (r != 0) { OS_REPORT_4(OS_ERROR, "os_signalHandlerInit", 0, "os_sigactionSet(%d, 0x%x, 0x%x) failed, result = %d", sig, &action, &old_signalHandler[sig], r); result = os_resultFail; assert(OS_FALSE); } } else { OS_REPORT_1(OS_INFO, "os_signalHandlerThread", 0, "Not installing a signal handler for the already ignored signal %d.", sig); } } else { OS_REPORT_1(OS_ERROR, "os_signalHandlerInit", 0, "Could not retrieve currently set signal-handler for signal %d", sig); result = os_resultFail; assert(OS_FALSE); } } } } } else { result = os_resultSuccess; } return result; }