static DWORD LwSmShutdownServices( VOID ) { DWORD dwError = 0; PWSTR* ppwszServiceNames = NULL; size_t i = 0; PSM_TABLE_ENTRY pEntry = NULL; SM_LOG_INFO("Shutting down running services"); dwError = LwSmTableEnumerateEntries(&ppwszServiceNames); BAIL_ON_ERROR(dwError); for (i = 0; ppwszServiceNames[i]; i++) { dwError = LwSmTableGetEntry(ppwszServiceNames[i], &pEntry); BAIL_ON_ERROR(dwError); dwError = LwSmShutdownService(pEntry); if (dwError) { /* Ignore errors and try to shut down everything we can */ SM_LOG_WARNING("Could not shut down service: %u\n", (unsigned int) dwError); dwError = 0; } LwSmTableReleaseEntry(pEntry); pEntry = NULL; } cleanup: if (ppwszServiceNames) { LwSmFreeStringList(ppwszServiceNames); } if (pEntry) { LwSmTableReleaseEntry(pEntry); } return dwError; error: goto cleanup; }
VOID LwSmTableNotifyEntryStateChanged( PSM_TABLE_ENTRY pEntry, LW_SERVICE_STATE state ) { DWORD error = ERROR_SUCCESS; BOOLEAN bLocked = FALSE; PSM_LINK pLink = NULL; PSM_LINK pNext = NULL; PSM_ENTRY_NOTIFY pNotify = NULL; PSTR pServiceName = NULL; time_t now = 0; LOCK(bLocked, pEntry->pLock); for (pLink = LwSmLinkBegin(&pEntry->waiters); LwSmLinkValid(&pEntry->waiters, pLink); pLink = pNext) { pNext = LwSmLinkNext(pLink); pNotify = STRUCT_FROM_MEMBER(pLink, SM_ENTRY_NOTIFY, link); LwSmLinkRemove(pLink); pNotify->pfnNotifyEntryStateChange(state, pNotify->pData); LwFreeMemory(pNotify); } pthread_cond_broadcast(pEntry->pEvent); if (state == LW_SERVICE_STATE_DEAD && gState.bWatchdog) { now = time(NULL); if (now == (time_t) -1) { error = LwErrnoToWin32Error(errno); BAIL_ON_ERROR(error); } error = LwWc16sToMbs(pEntry->pInfo->pwszName, &pServiceName); BAIL_ON_ERROR(error); if (pEntry->StartAttempts >= 1 && (now - pEntry->LastRestartPeriod) > RESTART_PERIOD) { pEntry->StartAttempts = 1; pEntry->LastRestartPeriod = now; } if (pEntry->StartAttempts > 0 && pEntry->StartAttempts < RESTART_LIMIT) { pEntry->StartAttempts++; pEntry->dwRefCount++; SM_LOG_WARNING( "Restarting dead service: %s (attempt %u/%u)", pServiceName, (unsigned int) pEntry->StartAttempts, (unsigned int) RESTART_LIMIT); error = LwNtStatusToWin32Error(LwRtlQueueWorkItem(gpPool, LwSmTableWatchdog, pEntry, 0)); if (error) { pEntry->dwRefCount--; } BAIL_ON_ERROR(error); } else if (pEntry->StartAttempts >= 1) { SM_LOG_ERROR( "Service died: %s (restarted %u times in %lu seconds)", pServiceName, (unsigned int) pEntry->StartAttempts, (unsigned long) (now - pEntry->LastRestartPeriod)); } else { SM_LOG_ERROR( "Service failed to start: %s", pServiceName); } } error: UNLOCK(bLocked, pEntry->pLock); LW_SAFE_FREE_MEMORY(pServiceName); }