/* * UpdateWorkerThread() -- thread for updating CellServDB of servers in * a single name block. */ static void * UpdateWorkerThread(void *argp) { afs_status_t sync_tst = 0; cfg_csdb_update_name_t *nameBlockp = (cfg_csdb_update_name_t *) argp; int opDisposition; /* Pthread mutex and condition variable functions should never fail, * but if they do make a best effort attempt to report the problem; * will not be able to avoid race conditions in the face of such failures. */ if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) { sync_tst = ADMMUTEXLOCK; } while ((opDisposition = nameBlockp->ctrl->disposition) == CSDB_WAIT) { /* wait for start/abort signal */ if (pthread_cond_wait (&nameBlockp->ctrl->event, &nameBlockp->ctrl->mutex)) { /* avoid tight loop if condition variable wait fails */ cfgutil_Sleep(1); } } if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) { sync_tst = ADMMUTEXUNLOCK; } if (opDisposition == CSDB_GO) { /* proceed with CellServDB update */ int i; for (i = 0; i < nameBlockp->serverCount; i++) { cfg_cellServDbStatus_t *statusp; /* alloc memory for status information (including host name) */ while ((statusp = (cfg_cellServDbStatus_t *) malloc(sizeof(*statusp) + AFS_MAX_SERVER_NAME_LEN)) == NULL) { /* avoid tight loop while waiting for status storage */ cfgutil_Sleep(1); } statusp->fsDbHost = ((char *)statusp + sizeof(*statusp)); /* make update and set status information */ strcpy(statusp->fsDbHost, nameBlockp->serverName[i]); if (sync_tst != 0) { /* report pthread problem */ statusp->status = sync_tst; } else { /* attempt update and report update status */ void *bosHandle; afs_status_t tst2, tst = 0; if (!bos_ServerOpen (nameBlockp->ctrl->cfg_host->cellHandle, nameBlockp->serverName[i], &bosHandle, &tst2)) { tst = tst2; } else { char *opHost = nameBlockp->ctrl->opHostAlias; if (nameBlockp->ctrl->op == CSDB_OP_ADD) { if (!bos_HostCreate(bosHandle, opHost, &tst2)) { tst = tst2; } } else { if (!bos_HostDelete(bosHandle, opHost, &tst2)) { if (tst2 != BZNOENT) { tst = tst2; } } } if (!bos_ServerClose(bosHandle, &tst2)) { tst = tst2; } } statusp->status = tst; } /* make call back to return update status */ (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId, statusp, 0); } } /* last worker makes termination call back and deallocates control block */ if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) { sync_tst = ADMMUTEXLOCK; } nameBlockp->ctrl->workersActive--; if (nameBlockp->ctrl->workersActive == 0) { if (opDisposition == CSDB_GO) { (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId, NULL, sync_tst); } free(nameBlockp->ctrl); } if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) { sync_tst = ADMMUTEXUNLOCK; } /* all workers deallocate their own name block */ free(nameBlockp); return NULL; }
/* * cfgutil_WindowsServiceStop() -- Stop a Windows service on local host. * * The value of timeout specifies the maximum time, in seconds, to wait * for the service to be in the SERVICE_STOPPED state. * * If service was already stopped/stopping then *wasStopped is true (1). * * RETURN CODES: 1 success, 0 failure (st indicates why) */ int cfgutil_WindowsServiceStop(LPCTSTR svcName, unsigned timeout, short *wasStopped, afs_status_p st) { int rc = 1; afs_status_t tst = 0; SC_HANDLE scmHandle, svcHandle; DWORD svcAccess = (SERVICE_STOP | SERVICE_QUERY_STATUS); *wasStopped = 0; if ((scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT)) == NULL || (svcHandle = OpenService(scmHandle, svcName, svcAccess)) == NULL) { /* can't connect to SCM or can't open service */ DWORD status = GetLastError(); if (status == ERROR_ACCESS_DENIED) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_NOPRIV); } else if (status == ERROR_SERVICE_DOES_NOT_EXIST) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_BAD); } else { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_STATUSUNK); } if (scmHandle != NULL) { CloseServiceHandle(scmHandle); } } else { /* service configured; attempt to stop */ SERVICE_STATUS svcStatus; if (!ControlService(svcHandle, SERVICE_CONTROL_STOP, &svcStatus)) { /* service stop failed */ DWORD status = GetLastError(); if (status == ERROR_SERVICE_NOT_ACTIVE) { *wasStopped = 1; } else { if (status == ERROR_ACCESS_DENIED) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_NOPRIV); } else if (status == ERROR_INVALID_SERVICE_CONTROL || status == ERROR_SERVICE_CANNOT_ACCEPT_CTRL || status == ERROR_SERVICE_REQUEST_TIMEOUT) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_NOTREADY); } else { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_BAD); } } } /* wait for service to be in SERVICE_STOPPED state */ if (tst == 0 && timeout > 0) { time_t timeStart = time(NULL); while (1) { if (!QueryServiceStatus(svcHandle, &svcStatus)) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_STATUSUNK); break; } else if (svcStatus.dwCurrentState == SERVICE_STOPPED) { break; } else if (difftime(time(NULL), timeStart) > timeout) { tst = ServiceCodeXlate(svcName, CFGUTIL_SVC_TIMEOUT); break; } else { /* sleep a bit and check state again */ cfgutil_Sleep(5); } } if (tst == 0) { /* wait just a bit more because we're paranoid */ cfgutil_Sleep(1); } } CloseServiceHandle(svcHandle); CloseServiceHandle(scmHandle); } if (tst != 0) { /* indicate failure */ rc = 0; } if (st != NULL) { *st = tst; } return rc; }