void WINAPI serviceMain()

in src/native/windows/apps/prunsrv/prunsrv.c [1670:1903]


void WINAPI serviceMain(DWORD argc, LPTSTR *argv)
{
    DWORD rc = 0;
    _service_status.dwServiceType      = SERVICE_WIN32_OWN_PROCESS;
    _service_status.dwCurrentState     = SERVICE_START_PENDING;
    _service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE;
    _service_status.dwWin32ExitCode    = 0;
    _service_status.dwCheckPoint       = 0;
    _service_status.dwWaitHint         = 0;
    _service_status.dwServiceSpecificExitCode = 0;

    apxLogWrite(APXLOG_MARK_DEBUG "Inside serviceMain()...");

    if (IS_VALID_STRING(_service_name)) {
        WCHAR en[SIZ_HUGLEN];
        int i;
        PSECURITY_ATTRIBUTES sa = GetNullACL();
        lstrlcpyW(en, SIZ_DESLEN, L"Global\\");
        lstrlcatW(en, SIZ_DESLEN, _service_name);
        lstrlcatW(en, SIZ_DESLEN, PRSRV_SIGNAL);
        for (i = 7; i < lstrlenW(en); i++) {
            if (en[i] == L' ')
                en[i] = L'_';
            else
                en[i] = towupper(en[i]);
        }
        gSignalEvent = CreateEventW(sa, TRUE, FALSE, en);
        CleanNullACL((void *)sa);

        if (gSignalEvent) {
            DWORD tid;
            gSignalThread = CreateThread(NULL, 0, eventThread, NULL, 0, &tid);
        }
    }
    /* Check the StartMode */
    if (IS_VALID_STRING(SO_STARTMODE)) {
        if (!lstrcmpiW(SO_STARTMODE, PRSRV_JVM)) {
            _jni_startup = TRUE;
            if (IS_VALID_STRING(SO_STARTCLASS)) {
                _jni_rclass  = WideToANSI(SO_STARTCLASS);
                /* Exchange all dots with slashes */
                apxStrCharReplaceA(_jni_rclass, '.', '/');
            }
            else {
                /* Presume its main */
                _jni_rclass = WideToANSI(L"Main");
            }
            _jni_rparam = SO_STARTPARAMS;
        }
        else if (!lstrcmpiW(SO_STARTMODE, PRSRV_JAVA)) {
            LPWSTR jx = NULL, szJH = SO_JAVAHOME;
            if (!szJH)
                szJH = apxGetJavaSoftHome(gPool, FALSE);
            else if (!lstrcmpiW(szJH, PRSRV_JDK)) {
                /* Figure out the JDK JavaHome */
                szJH = apxGetJavaSoftHome(gPool, FALSE);
            }
            else if (!lstrcmpiW(szJH, PRSRV_JRE)) {
                /* Figure out the JRE JavaHome */
                szJH = apxGetJavaSoftHome(gPool, TRUE);
            }
            if (szJH) {
                jx = apxPoolAlloc(gPool, (lstrlenW(szJH) + 16) * sizeof(WCHAR));
                lstrcpyW(jx, szJH);
                lstrcatW(jx, PRSRV_JBIN);
                if (!SO_STARTPATH) {
                    /* Use JAVA_HOME/bin as start path */
                    LPWSTR szJP = apxPoolAlloc(gPool, (lstrlenW(szJH) + 8) * sizeof(WCHAR));
                    lstrcpyW(szJP, szJH);
                    lstrcatW(szJP, PRSRV_PBIN);
                    SO_STARTPATH = szJP;
                }
            }
            else {
                apxLogWrite(APXLOG_MARK_ERROR "Unable to find Java Runtime Environment.");
                goto cleanup;
            }
            _java_startup = TRUE;
            /* StartImage now contains the full path to the java.exe */
            SO_STARTIMAGE = jx;
        }
    }
    /* Check the StopMode */
    if (IS_VALID_STRING(SO_STOPMODE)) {
        if (!lstrcmpiW(SO_STOPMODE, PRSRV_JVM)) {
            _jni_shutdown = TRUE;
            if (IS_VALID_STRING(SO_STOPCLASS)) {
                _jni_sclass = WideToANSI(SO_STOPCLASS);
                apxStrCharReplaceA(_jni_sclass, '.', '/');
            }
            else {
                /* Defaults to Main */
                _jni_sclass = WideToANSI(L"Main");
            }
            _jni_sparam = SO_STOPPARAMS;
        }
        else if (!lstrcmpiW(SO_STOPMODE, PRSRV_JAVA)) {
            LPWSTR jx = NULL, szJH = SO_JAVAHOME;
            if (!szJH)
                szJH = apxGetJavaSoftHome(gPool, FALSE);
            else if (!lstrcmpiW(szJH, PRSRV_JDK)) {
                /* Figure out the JDK JavaHome */
                szJH = apxGetJavaSoftHome(gPool, FALSE);
            }
            else if (!lstrcmpiW(szJH, PRSRV_JRE)) {
                /* Figure out the JRE JavaHome */
                szJH = apxGetJavaSoftHome(gPool, TRUE);
            }
            if (szJH) {
                jx = apxPoolAlloc(gPool, (lstrlenW(szJH) + 16) * sizeof(WCHAR));
                lstrcpyW(jx, szJH);
                lstrcatW(jx, PRSRV_JBIN);
                if (!SO_STOPPATH) {
                    LPWSTR szJP = apxPoolAlloc(gPool, (lstrlenW(szJH) + 8) * sizeof(WCHAR));
                    lstrcpyW(szJP, szJH);
                    lstrcatW(szJP, PRSRV_PBIN);
                    /* Use JAVA_HOME/bin as stop path */
                    SO_STOPPATH = szJP;
                }
            }
            else {
                apxLogWrite(APXLOG_MARK_ERROR "Unable to find Java Runtime Environment.");
                goto cleanup;
            }
            _java_shutdown = TRUE;
            /* StopImage now contains the full path to the java.exe */
            SO_STOPIMAGE = jx;
        }
    }
    /* Find the classpath */
    if (_jni_shutdown || _jni_startup) {
        if (IS_VALID_STRING(SO_JVM)) {
            if (lstrcmpW(SO_JVM, PRSRV_AUTO))
                _jni_jvmpath = SO_JVM;
        }
        if (IS_VALID_STRING(SO_CLASSPATH))
            _jni_classpath = WideToANSI(SO_CLASSPATH);
        if (IS_VALID_STRING(SO_STARTMETHOD))
            _jni_rmethod   = WideToANSI(SO_STARTMETHOD);
        if (IS_VALID_STRING(SO_STOPMETHOD))
            _jni_smethod   = WideToANSI(SO_STOPMETHOD);
        _jni_jvmoptions    = MzWideToANSI(SO_JVMOPTIONS);
        _jni_jvmoptions9   = MzWideToANSI(SO_JVMOPTIONS9);
    }
    if (_service_mode) {
        /* Register Service Control handler */
        _service_status_handle = RegisterServiceCtrlHandlerW(_service_name,
                                                              service_ctrl_handler);
        if (IS_INVALID_HANDLE(_service_status_handle)) {
            apxLogWrite(APXLOG_MARK_ERROR "Failed to register Service Control for '%S'.",
                        _service_name);
            goto cleanup;
        }
        /* Allocate console so that events gets processed */
        if (!AttachConsole(ATTACH_PARENT_PROCESS) &&
             GetLastError() == ERROR_INVALID_HANDLE) {
            HWND hc;
            AllocConsole();
            if ((hc = GetConsoleWindow()) != NULL)
                ShowWindow(hc, SW_HIDE);
        }
    }
    reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
    if ((rc = serviceStart()) == 0) {
        /* Service is started */
        reportServiceStatus(SERVICE_RUNNING, NO_ERROR, 0);
        apxLogWrite(APXLOG_MARK_DEBUG "Waiting for worker to finish...");
        /* Set console handler to capture CTRL events */
        SetConsoleCtrlHandler((PHANDLER_ROUTINE)console_handler, TRUE);

        if (SO_STOPTIMEOUT) {
            /* we have a stop timeout */
            BOOL bLoopWarningIssued = FALSE;
            do {
                /* wait 2 seconds */
                DWORD rv = apxHandleWait(gWorker, 2000, FALSE);
                if (rv == WAIT_OBJECT_0 && !_exe_shutdown) {
                    if (!bLoopWarningIssued) {
                        apxLogWrite(APXLOG_MARK_WARN "Start method returned before stop method was called. This should not happen. Using loop with a fixed sleep of 2 seconds waiting for stop method to be called.");
                        bLoopWarningIssued = TRUE;
                    }
                    Sleep(2000);
                }
            } while (!_exe_shutdown);
            apxLogWrite(APXLOG_MARK_DEBUG "waiting %d sec... shutdown: %d", SO_STOPTIMEOUT, _exe_shutdown);
            apxHandleWait(gWorker, SO_STOPTIMEOUT*1000, FALSE);
        } else {
            apxHandleWait(gWorker, INFINITE, FALSE);
        }
        apxLogWrite(APXLOG_MARK_DEBUG "Worker finished.");
    }
    else {
        apxLogWrite(APXLOG_MARK_ERROR "ServiceStart returned %d.", rc);
        goto cleanup;
    }
    if (gShutdownEvent) {

        /* Ensure that shutdown thread exits before us */
        apxLogWrite(APXLOG_MARK_DEBUG "Waiting for ShutdownEvent.");
        reportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, ONE_MINUTE);
        WaitForSingleObject(gShutdownEvent, ONE_MINUTE);
        apxLogWrite(APXLOG_MARK_DEBUG "ShutdownEvent signaled.");
        CloseHandle(gShutdownEvent);
        gShutdownEvent = NULL;

        /* This will cause to wait for all threads to exit
         */
        apxLogWrite(APXLOG_MARK_DEBUG "Waiting 1 minute for all threads to exit.");
        reportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, ONE_MINUTE);
        apxDestroyJvm(ONE_MINUTE);
        /* if we are not using JAVA apxDestroyJvm does nothing, check the chid processes in case they hang */
        apxProcessTerminateChild( GetCurrentProcessId(), FALSE); /* FALSE kills! */
    }
    else {
        /* We came here without shutdown event
         * Probably because main() returned without ensuring all threads
         * have finished
         */
        apxLogWrite(APXLOG_MARK_DEBUG "Waiting for all threads to exit.");
        apxDestroyJvm(INFINITE);
        reportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
    }
    apxLogWrite(APXLOG_MARK_DEBUG "JVM destroyed.");
    reportServiceStatusStopped(apxGetVmExitCode());

    return;
cleanup:
    /* Cleanup */
    reportServiceStatusStopped(rc);
    gExitval = rc;
    return;
    UNREFERENCED_PARAMETER(argc);
    UNREFERENCED_PARAMETER(argv);
}