u_result u_userAddDomain( u_domain domain) { u_domainAdmin ka; u_user u; u_result result; os_sharedHandle shm; os_result osr; if(domain) { u = u__userLock(); if(u){ if (u->domainCount + 1 < MAX_DOMAINS) { shm = u_domainSharedMemoryHandle(domain); u->domainCount++; ka = &u->domainList[u->domainCount]; ka->domain = domain; /* The keepList holds all domain references issues by * u_userKeep(). * This list will keep the objects alive until the objects * are removed by u_userFree() or when the domain is detached * from the process e.g. when a process terminates. */ ka->keepList = NULL; ka->lowerBound = (c_address)os_sharedAddress(shm); osr = os_sharedSize(shm, (os_address*)&ka->upperBound); if (osr != os_resultSuccess) { OS_REPORT(OS_ERROR, "u_userAddDomain",0, "shared memory size cannot be determined"); result = U_RESULT_INTERNAL_ERROR; } else { result = U_RESULT_OK; } ka->upperBound += ka->lowerBound; } else { OS_REPORT_1(OS_ERROR, "u_userAddDomain",0, "Max connected Domains (%d) reached!", MAX_DOMAINS - 1); result = U_RESULT_OUT_OF_MEMORY; } u__userUnlock(); } else { OS_REPORT(OS_ERROR, "u_userAddDomain",0, "User layer not initialized"); result = U_RESULT_PRECONDITION_NOT_MET; } } else { OS_REPORT(OS_ERROR, "u_userAddDomain",0, "Invalid Domain specified: Domain = NULL"); result = U_RESULT_ILL_PARAM; } /* Fail already reported by u_domainNew */ return result; }
static void* shmMonitorMain( void* arg) { os_sharedHandle shmHandle; u_result cleanupResult; os_result result; os_duration blockingTime = 10*OS_DURATION_MILLISECOND; os_shmClient clients, client; s_shmMonitor _this = (s_shmMonitor)arg; os_procId ownPID; ownPID = os_procIdSelf(); shmHandle = u_domainSharedMemoryHandle( u_participantDomain( u_participant( splicedGetService(_this->spliceDaemon)))); os_mutexLock(&_this->mutex); while(_this->terminate == OS_FALSE){ clients = NULL; os_mutexUnlock(&_this->mutex); ut_threadAsleep(_this->thr, 1); result = os_sharedMemoryWaitForClientChanges(shmHandle, blockingTime, &clients); os_mutexLock(&_this->mutex); if(result == os_resultSuccess){ client = clients; _this->shmState = SHM_STATE_UNKNOWN; while(client){ if(client->state == OS_SHM_PROC_TERMINATED){ if(client->procId != ownPID){ OS_REPORT(OS_WARNING, OSRPT_CNTXT_SPLICED, 0, "Detected termination of process %d, that failed " "to clean up its resources before terminating. " "Attempting to clean up its resources now..." , client->procId); os_mutexUnlock(&_this->mutex); /* Allow the u_splicedCleanupProcessInfo() to take as * long as MAX(leasePeriod, serviceTerminatePeriod). * This is set in the threadsMonitor as the threads * interval. * By indicating that it'll sleep for 1 second, it * is allowed to stay dormant for that 1 second plus * the threads interval. */ ut_threadAsleep(_this->thr, 1); cleanupResult = u_splicedCleanupProcessInfo(splicedGetService(_this->spliceDaemon), client->procId); os_mutexLock(&_this->mutex); if(cleanupResult != U_RESULT_OK){ OS_REPORT(OS_FATAL, OSRPT_CNTXT_SPLICED, 0, "Cleaning up resources of terminated process " "%d failed, because process was modifying " "shared resources when it terminated, " "stopping domain now...", client->procId); _this->shmState = SHM_STATE_UNCLEAN; os_condSignal(&_this->cleanCondition); splicedSignalTerminate(_this->spliceDaemon, SPLICED_EXIT_CODE_RECOVERABLE_ERROR, SPLICED_SHM_NOK); } else { OS_REPORT(OS_INFO, OSRPT_CNTXT_SPLICED, 0, "Successfully cleaned up resources of " "terminated process %d.", client->procId); } } else { OS_REPORT(OS_FATAL, OSRPT_CNTXT_SPLICED, 0, "Detected unexpected detach of kernel by my own " "process, stopping domain now..."); _this->shmState = SHM_STATE_UNCLEAN; os_condSignal(&_this->cleanCondition); splicedSignalTerminate(_this->spliceDaemon, SPLICED_EXIT_CODE_RECOVERABLE_ERROR, SPLICED_SHM_NOK); } ut_threadAwake(_this->thr); } client = client->next; } os_shmClientFree(clients); if (_this->shmState == SHM_STATE_UNKNOWN) { _this->shmState = SHM_STATE_CLEAN; os_condSignal(&_this->cleanCondition); } } else if (result == os_resultUnavailable) { /* client list is empty so we need to give up some cpu time * in order that it can be initialised on non timesliced systems * e.g. vxworks kernel builds */ ut_sleep(_this->thr, 100*OS_DURATION_MICROSECOND); } } os_mutexUnlock(&_this->mutex); return NULL; }