diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17a6361b67..c995358c82 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,6 @@ on: push: branches: [ 'sustaining/4.10.x','master' ] pull_request: - branches: [ 'sustaining/4.10.x','master' ] jobs: build-maven: @@ -28,17 +27,17 @@ jobs: wine --version version="9.4.0"; sudo wget "https://dl.winehq.org/wine/wine-mono/$version/wine-mono-$version-x86.msi" -O /tmp/wine-mono.msi wine msiexec /i /tmp/wine-mono.msi - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive - name: Java ${{ matrix.Java }} (${{ matrix.os }}) - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: ${{ matrix.java }} distribution: 'zulu' - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.m2/repository key: ${{ runner.os }}-m2-repository-${{ hashFiles('**/pom.xml') }} @@ -247,21 +246,23 @@ jobs: opendj-server-legacy\target\package\opendj\bat\stop-ds.bat opendj-server-legacy\target\package\opendj\bat\windows-service.bat --enableService net start "OpenDJ Server" + if ($LASTEXITCODE -ne 0) { throw "net start 'OpenDJ Server' failed with exit code $LASTEXITCODE" } for ($i=0; $i -lt 12; $i++) { try { $c = New-Object System.Net.Sockets.TcpClient('localhost', 1636); $c.Close(); break } catch { Start-Sleep -Seconds 5 } } opendj-server-legacy\target\package\opendj\bat\ldapsearch.bat --hostname localhost --port 1636 --bindDN "cn=Directory Manager" --bindPassword password --useSsl --trustAll --baseDN "dc=example2,dc=com" --searchScope sub "(uid=user.*)" dn | find /c '"dn:"' | findstr "10000" net stop "OpenDJ Server" + if ($LASTEXITCODE -ne 0) { throw "net stop 'OpenDJ Server' failed with exit code $LASTEXITCODE" } opendj-server-legacy\target\package\opendj\bat\windows-service.bat --disableService - name: Upload Windows exe artifacts if: runner.os == 'Windows' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: windows-exe-${{ matrix.java }} retention-days: 5 path: opendj-server-legacy/src/build-tools/windows/*.exe - name: Upload artifacts OpenDJ Server - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.os }}-${{ matrix.java }} retention-days: 5 @@ -286,7 +287,7 @@ jobs: - 5000:5000 steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: ubuntu-latest-11 - name: Get latest release version @@ -296,16 +297,16 @@ jobs: echo "release_version=$git_version_last" >> $GITHUB_ENV - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | localhost:5000/${{ github.repository }} tags: | type=raw,value=${{ env.release_version }} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 with: driver-opts: network=host - name: Prepare Dockerfile @@ -315,7 +316,7 @@ jobs: cp ./opendj-server-legacy/target/package/opendj-*.zip ./opendj-packages/opendj-docker sed -i -E '/^#COPY opendj/s/^#//' ./opendj-packages/opendj-docker/Dockerfile - name: Build image (default) - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: context: ./opendj-packages/opendj-docker file: ./opendj-packages/opendj-docker/Dockerfile @@ -350,7 +351,7 @@ jobs: - 5000:5000 steps: - name: Download artifacts - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: ubuntu-latest-11 - name: Get latest release version @@ -360,7 +361,7 @@ jobs: echo "release_version=$git_version_last" >> $GITHUB_ENV - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | localhost:5000/${{ github.repository }} @@ -368,9 +369,9 @@ jobs: type=raw,value=alpine type=raw,value=${{ env.release_version }}-alpine - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 with: driver-opts: network=host - name: Prepare Dockerfile @@ -380,7 +381,7 @@ jobs: cp ./opendj-server-legacy/target/package/opendj-*.zip ./opendj-packages/opendj-docker sed -i -E '/^#COPY opendj/s/^#//' ./opendj-packages/opendj-docker/Dockerfile-alpine - name: Build image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: context: ./opendj-packages/opendj-docker file: ./opendj-packages/opendj-docker/Dockerfile-alpine diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c6e0b5184b..8b56d45faa 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -27,13 +27,13 @@ jobs: wine --version version="9.4.0"; sudo wget "https://dl.winehq.org/wine/wine-mono/$version/wine-mono-$version-x86.msi" -O /tmp/wine-mono.msi wine msiexec /i /tmp/wine-mono.msi - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive ref: ${{ github.event.workflow_run.head_branch }} - name: Set up Java for publishing to Maven Central Repository OSS - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: ${{ github.event.workflow_run.head_branch == 'sustaining/4.10.x' && '8' || '11'}} distribution: 'temurin' @@ -41,7 +41,7 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.m2/repository key: ${{ runner.os }}-m2-repository-${{ hashFiles('**/pom.xml') }} @@ -71,52 +71,52 @@ jobs: continue-on-error: true run: mvn javadoc:aggregate - name: Upload artifacts OpenDJ Server - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Server path: opendj-server-legacy/target/package/*.zip - name: Upload artifacts OpenDJ SDK Toolkit - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ SDK Toolkit path: opendj-ldap-toolkit/target/*.zip - name: Upload artifacts OpenDJ Debian Package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Debian Package path: opendj-packages/opendj-deb/opendj-deb-standard/target/*.deb - name: Upload artifacts OpenDJ RPM Package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ RPM Package path: opendj-packages/opendj-rpm/opendj-rpm-standard/target/rpm/opendj/RPMS/noarch/*.rpm - name: Upload artifacts OpenDJ MSI Package - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ MSI Package path: opendj-packages/opendj-msi/opendj-msi-standard/target/*.msi - name: Upload artifacts OpenDJ Docker Packages - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Docker Packages path: opendj-packages/opendj-docker/target/Dockerfile.zip - name: Upload artifacts OpenDJ Openshift template - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Openshift template path: opendj-packages/opendj-openshift-template/*.yaml - name: Upload artifacts OpenDJ Doc Generated Reference - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Doc Generated References path: opendj-doc-generated-ref/target/*.zip - name: Upload artifacts OpenDJ DSML Gateway - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ DSML Gateway path: opendj-dsml-servlet/target/*.war - name: Upload artifacts OpenDJ Commons REST LDAP Gateway - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: OpenDJ Commons REST LDAP Gateway path: opendj-rest2ldap-servlet/target/*.war @@ -125,7 +125,7 @@ jobs: git config --global user.name "Open Identity Platform Community" git config --global user.email "open-identity-platform-opendj@googlegroups.com" cd .. - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 continue-on-error: true with: repository: ${{ github.repository }}.wiki @@ -145,7 +145,7 @@ jobs: git commit -a -m "upload docs after deploy ${{ github.sha }}" git push --quiet --force - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 continue-on-error: true with: repository: OpenIdentityPlatform/doc.openidentityplatform.org diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9b982ac93b..41bb3bc8b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,12 +31,12 @@ jobs: wine --version version="9.4.0"; sudo wget "https://dl.winehq.org/wine/wine-mono/$version/wine-mono-$version-x86.msi" -O /tmp/wine-mono.msi wine msiexec /i /tmp/wine-mono.msi - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: fetch-depth: 0 submodules: recursive - name: Set up Java for publishing to Maven Central Repository OSS - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: ${{ github.event.workflow_run.head_branch == 'sustaining/4.10.x' && '8' || '11'}} distribution: 'temurin' @@ -44,7 +44,7 @@ jobs: server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD - name: Cache Maven packages - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.m2/repository key: ${{ runner.os }}-m2-repository-${{ hashFiles('**/pom.xml') }} @@ -90,7 +90,7 @@ jobs: target/checkout/opendj-doc-generated-ref/target/*.zip target/checkout/opendj-dsml-servlet/target/*.war target/checkout/opendj-rest2ldap-servlet/target/*.war - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 continue-on-error: true with: repository: ${{ github.repository }}.wiki @@ -113,7 +113,7 @@ jobs: git push --quiet --force git push --quiet --force origin ${{ github.event.inputs.releaseVersion }} - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 continue-on-error: true with: repository: OpenIdentityPlatform/doc.openidentityplatform.org @@ -136,14 +136,14 @@ jobs: needs: - release-maven steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ github.event.inputs.releaseVersion }} fetch-depth: 1 submodules: recursive - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ${{ github.repository }} @@ -152,22 +152,22 @@ jobs: type=raw,value=latest type=raw,value=${{ github.event.inputs.releaseVersion }} - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GHCR - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 continue-on-error: true with: context: ./opendj-packages/opendj-docker @@ -184,14 +184,14 @@ jobs: needs: - release-maven steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: ref: ${{ github.event.inputs.releaseVersion }} fetch-depth: 1 submodules: recursive - name: Docker meta id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@v6 with: images: | ${{ github.repository }} @@ -200,23 +200,23 @@ jobs: type=raw,value=alpine type=raw,value=${{ github.event.inputs.releaseVersion }}-alpine - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + uses: docker/setup-qemu-action@v4 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@v4 - name: Login to DockerHub - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GHCR - uses: docker/login-action@v3 + uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push image continue-on-error: true - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v7 with: context: ./opendj-packages/opendj-docker file: ./opendj-packages/opendj-docker/Dockerfile-alpine diff --git a/opendj-server-legacy/lib/launcher_administrator.exe b/opendj-server-legacy/lib/launcher_administrator.exe index bf71337cc1..50b885811d 100644 Binary files a/opendj-server-legacy/lib/launcher_administrator.exe and b/opendj-server-legacy/lib/launcher_administrator.exe differ diff --git a/opendj-server-legacy/lib/opendj_service.exe b/opendj-server-legacy/lib/opendj_service.exe index e4f456c8eb..0b458d8f72 100644 Binary files a/opendj-server-legacy/lib/opendj_service.exe and b/opendj-server-legacy/lib/opendj_service.exe differ diff --git a/opendj-server-legacy/lib/winlauncher.exe b/opendj-server-legacy/lib/winlauncher.exe old mode 100755 new mode 100644 index f971e1b7d5..04f210cb64 Binary files a/opendj-server-legacy/lib/winlauncher.exe and b/opendj-server-legacy/lib/winlauncher.exe differ diff --git a/opendj-server-legacy/src/build-tools/windows/service.c b/opendj-server-legacy/src/build-tools/windows/service.c index 42082bc2e3..1fd7e373d0 100644 --- a/opendj-server-legacy/src/build-tools/windows/service.c +++ b/opendj-server-legacy/src/build-tools/windows/service.c @@ -503,7 +503,7 @@ ServiceReturnCode isServerRunning(BOOL *running, BOOL mustDebug) // The functions returns SERVICE_RETURN_OK if we could start the server // and SERVICE_RETURN_ERROR otherwise. // ---------------------------------------------------- -ServiceReturnCode doStartApplication() +ServiceReturnCode doStartApplication(SERVICE_STATUS_HANDLE *serviceStatusHandle, DWORD *checkPoint) { ServiceReturnCode returnValue; // init out params @@ -546,6 +546,11 @@ ServiceReturnCode doStartApplication() debug("doStartApplication: OPENDJ_WINDOWS_SERVICE_STARTDS_WAIT is not set. Using default %d milliseconds.", STARTDS_WAIT_DEFAULT_VALUE); } + if (serviceStatusHandle != NULL && checkPoint != NULL) + { + updateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, + (*checkPoint)++, wait + 30000, serviceStatusHandle); + } waitOk = waitForProcess(&procInfo, wait, &startDSExit); if (waitOk) { @@ -590,6 +595,11 @@ ServiceReturnCode doStartApplication() while ((nTries > 0) && !running) { nTries--; + if (serviceStatusHandle != NULL && checkPoint != NULL) + { + updateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, + (*checkPoint)++, 10000, serviceStatusHandle); + } if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK) { break; @@ -640,6 +650,11 @@ ServiceReturnCode doStartApplication() while ((nTries > 0) && !running) { nTries--; + if (serviceStatusHandle != NULL && checkPoint != NULL) + { + updateServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, + (*checkPoint)++, 10000, serviceStatusHandle); + } if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK) { break; @@ -700,7 +715,7 @@ ServiceReturnCode doStopApplication() if (spawn(command, FALSE) != -1) { // Try to see if server is really stopped - int nTries = 10; + int nTries = 30; BOOL running = TRUE; debug("doStopApplication: the spawn of the process worked."); @@ -710,6 +725,7 @@ ServiceReturnCode doStopApplication() Sleep(3000); while ((nTries > 0) && running) { + nTries--; if (isServerRunning(&running, TRUE) != SERVICE_RETURN_OK) { break; @@ -1118,7 +1134,7 @@ void serviceMain(int argc, char* argv[]) { WORD argCount = 1; const char *argc[] = {_instanceDir}; - code = doStartApplication(); + code = doStartApplication(_serviceStatusHandle, &checkPoint); switch (code) { @@ -1225,31 +1241,53 @@ void serviceMain(int argc, char* argv[]) } else { - // Check current Status - DWORD state; - BOOL success = getServiceStatus(serviceName, &state); - if (!(success && - ((state == SERVICE_STOPPED) || - (state == SERVICE_STOP_PENDING)))) + // Server appears not running - retry a few times before concluding + // it has actually stopped (the lock file check can be transient, + // e.g. during JVM GC pressure or heavy I/O after a large ldapsearch). + // 3 retries × 2 seconds gives up to 6 extra seconds of tolerance. + int retryCount = 3; + BOOL confirmedStopped = TRUE; + while (retryCount > 0) { - WORD argCount = 1; - const char *argc[] = {_instanceDir}; - _serviceCurStatus = SERVICE_STOPPED; - debug("checking in serviceMain serviceHandler: service stopped with error."); + retryCount--; + Sleep(2000); // wait 2 seconds between retries before re-checking + code = isServerRunning(&running, TRUE); + if (code == SERVICE_RETURN_OK && running) + { + confirmedStopped = FALSE; + break; + } + } - updateServiceStatus ( - _serviceCurStatus, - ERROR_SERVICE_SPECIFIC_ERROR, - -1, - CHECKPOINT_NO_ONGOING_OPERATION, - TIMEOUT_NONE, - _serviceStatusHandle); - reportLogEvent( - EVENTLOG_ERROR_TYPE, - WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM, - argCount, argc); - } - break; + if (confirmedStopped) + { + // Check current Status + DWORD state; + BOOL success = getServiceStatus(serviceName, &state); + if (!(success && + ((state == SERVICE_STOPPED) || + (state == SERVICE_STOP_PENDING)))) + { + WORD argCount = 1; + const char *argc[] = {_instanceDir}; + _serviceCurStatus = SERVICE_STOPPED; + debug("checking in serviceMain serviceHandler: service stopped with error."); + + updateServiceStatus ( + _serviceCurStatus, + ERROR_SERVICE_SPECIFIC_ERROR, + -1, + CHECKPOINT_NO_ONGOING_OPERATION, + TIMEOUT_NONE, + _serviceStatusHandle); + reportLogEvent( + EVENTLOG_ERROR_TYPE, + WIN_EVENT_ID_SERVER_STOPPED_OUTSIDE_SCM, + argCount, argc); + } + break; + } + // else: server is actually still running, continue monitoring } } } diff --git a/opendj-server-legacy/src/build-tools/windows/service.h b/opendj-server-legacy/src/build-tools/windows/service.h index 6d6b933cba..d75debac0f 100644 --- a/opendj-server-legacy/src/build-tools/windows/service.h +++ b/opendj-server-legacy/src/build-tools/windows/service.h @@ -13,6 +13,7 @@ * * Copyright 2008 Sun Microsystems, Inc. * Portions Copyright 2013 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ #include "common.h" @@ -95,6 +96,7 @@ ServiceReturnCode updateServiceStatus ( DWORD waitHint, SERVICE_STATUS_HANDLE *serviceStatusHandle ); +ServiceReturnCode doStartApplication(SERVICE_STATUS_HANDLE *serviceStatusHandle, DWORD *checkPoint); void serviceHandler(DWORD controlCode); BOOL getServiceStatus(char *serviceName, LPDWORD returnState);