billbarker 2003/08/08 18:59:42 Modified: daemon/src/native/nt/procrun procrun.c procrun.h daemon/src/native/nt/procrun/bin procrun.dll procrun.exe procrunw.exe tomcat.exe tomcatw.exe Log: Some changes to cleanup the startup and shutdown. Fix for Bugs: 22174 and 21279 -- procrun now waits for the shutdown to finish before killing the JVM -- procrun strips quotes if running under JNI (so the user doesn't have to) -- Added a --Environment configuration parameter for the forking case -- Fixed problems where handles were getting closed twice (which XP doesn't like). Revision Changes Path 1.26 +174 -72 jakarta-commons-sandbox/daemon/src/native/nt/procrun/procrun.c Index: procrun.c =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/daemon/src/native/nt/procrun/procrun.c,v retrieving revision 1.25 retrieving revision 1.26 diff -u -r1.25 -r1.26 --- procrun.c 8 Aug 2003 10:34:31 -0000 1.25 +++ procrun.c 9 Aug 2003 01:59:42 -0000 1.26 @@ -102,6 +102,8 @@ JNI_GETCREATEDJAVAVMS jni_JNI_GetCreatedJavaVMs = NULL; int report_service_status(DWORD, DWORD, DWORD, process_t *); +int procrun_redirect(char *program, char **envp, procrun_t *env, int starting); + static int g_proc_stderr_file = 0; int g_proc_mode = 0; /* The main envronment for services */ @@ -246,6 +248,18 @@ return h; } +static BOOL pool_close_handle(pool_t *pool, HANDLE h) +{ + int i; + EnterCriticalSection(&pool->lock); + for(i=0; i < pool->size; i++) { + if(pool->mp[i].h == h) + pool->mp[i].h = INVALID_HANDLE_VALUE; + } + LeaveCriticalSection(&pool->lock); + return CloseHandle(h); +} + static void simple_encrypt(int seed, const char *str, unsigned char bytes[256]) { int i; @@ -461,6 +475,17 @@ return i; } +static char *remove_quotes(char * string) { + char *p = string, *q = string; + while (*p) { + if(*p != '\"' && *p != '\'') + *q++ = *p; + ++p; + } + *q = '\0'; + return string; +} + /* Parse command line argument. * First command param starts with //name//value */ @@ -909,7 +934,7 @@ NULL); if (proc->service.infile != INVALID_HANDLE_VALUE) { if (proc->h_stdin[1] != INVALID_HANDLE_VALUE) - CloseHandle(proc->h_stdin[1]); + pool_close_handle(proc->pool, proc->h_stdin[1]); proc->h_stdin[1] = proc->service.infile; proc->service.inname = pool_strdup(proc->pool, kval); } @@ -929,7 +954,7 @@ if (proc->service.outfile != INVALID_HANDLE_VALUE) { SetFilePointer(proc->service.outfile, 0L, NULL, FILE_END); if (proc->h_stdout[1] != INVALID_HANDLE_VALUE) - CloseHandle(proc->h_stdout[1]); + pool_close_handle(proc->pool, proc->h_stdout[1]); proc->h_stdout[1] = proc->service.outfile; proc->service.outname = pool_strdup(proc->pool, kval); } @@ -949,7 +974,7 @@ if (proc->service.errfile != INVALID_HANDLE_VALUE) { SetFilePointer(proc->service.errfile, 0L, NULL, FILE_END); if (proc->h_stderr[1] != INVALID_HANDLE_VALUE) - CloseHandle(proc->h_stderr[1]); + pool_close_handle(proc->pool, proc->h_stderr[1]); proc->h_stderr[1] = proc->service.errfile; proc->service.errname = pool_strdup(proc->pool, kval); } @@ -985,6 +1010,17 @@ &ac_winpos.top, &ac_winpos.bottom); } #endif + if ((err = RegQueryValueEx(key, PROCRUN_PARAMS_ENVIRONMENT, NULL, NULL, + NULL, + &klen)) == ERROR_SUCCESS) { + proc->service.environment = (char *)pool_alloc(proc->pool, klen); + if ((err = RegQueryValueEx(key, PROCRUN_PARAMS_ENVIRONMENT, NULL, NULL, + (unsigned char *)proc->service.environment, + &klen)) != ERROR_SUCCESS) { + proc->service.environment = NULL; + } + } + RegCloseKey(key); return 0; } @@ -1048,6 +1084,9 @@ DBPRINTF1("java bin %s\n", proc->java.jbin); if (!proc->java.path || !proc->java.start_method) return -1; + else if (proc->java.jbin != NULL) { + return 0; // If forking, don't bother with the load. + } /* Try to load the jvm dll */ em = SetErrorMode(SEM_FAILCRITICALERRORS); proc->java.dll = LoadLibraryEx(proc->java.path, NULL, 0); @@ -1134,14 +1173,28 @@ return (*jvm)->DetachCurrentThread(jvm); } -static int procrun_destroy_jvm(process_t *proc) +static int procrun_destroy_jvm(process_t *proc, HANDLE jh) { JavaVM *jvm = proc->java.jvm; int err; JNIEnv *env; - if (!proc->java.dll || !jvm) + if (!proc->java.dll || !jvm) { + if(proc->java.stop_class != NULL && proc->java.stop_method != NULL && g_env->c->pinfo.dwProcessId) { + process_t tc = *g_env->c, tm = *g_env->m; + procrun_t tproc; + HANDLE threads[2]; + tproc.c = &tc; + tproc.m = &tm; + procrun_redirect(proc->service.image, + proc->envp, &tproc, 0); + threads[0] = tc.pinfo.hThread; + threads[1] = g_env->c->pinfo.hThread; + WaitForMultipleObjects(2,threads, TRUE, 60000); + } + return 0; + } env = jni_attach(proc); if (!env) goto cleanup; @@ -1160,6 +1213,8 @@ proc->java.stop_bridge, proc->java.stop_mid, jargs); + if(jh != NULL) + WaitForSingleObject(jh, 60000); } else if (!proc->java.jbin) { /* Call java.lang.System.exit(0) */ @@ -1214,11 +1269,11 @@ optn = make_array(proc->java.opts, opts, 30, proc); for (i = 0; i < optn; i++) - options[i].optionString = opts[i]; + options[i].optionString = remove_quotes(opts[i]); cp = (char *)pool_alloc(proc->pool, strlen("-Djava.class.path=") + strlen(proc->service.image) + 1); strcpy(cp, "-Djava.class.path="); - strcat(cp, proc->service.image); + strcat(cp, remove_quotes(proc->service.image)); options[optn++].optionString = cp; DBPRINTF1("-Djava.class.path=%s", proc->service.image); /* Set the abort and exit hooks */ @@ -1271,7 +1326,7 @@ proc->java.stop_class[i] = '/'; } proc->java.stop_bridge = (*env)->FindClass(env, proc->java.stop_class); - if (!proc->java.start_bridge) { + if (!proc->java.stop_bridge) { goto cleanup; } proc->java.stop_mid = (*env)->GetStaticMethodID(env, proc->java.stop_bridge, @@ -1315,7 +1370,7 @@ Sleep(1000); WaitForSingleObject(env->c->pinfo.hThread, INFINITE); - CloseHandle(env->c->pinfo.hThread); + pool_close_handle(env->c->pool, env->c->pinfo.hThread); env->c->pinfo.hThread = NULL; env->c->pinfo.dwProcessId = 0; SetEvent(env->m->events[1]); @@ -1443,7 +1498,7 @@ DBPRINTF0(NULL); return -1; } - CloseHandle(env->c->h_stdout[0]); + pool_close_handle(env->c->pool, env->c->h_stdout[0]); pool_handle(env->c->pool, env->c->h_stdout[3]); /* redirect stderr */ @@ -1468,7 +1523,7 @@ DBPRINTF0(NULL); return -1; } - CloseHandle(env->c->h_stderr[0]); + pool_close_handle(env->c->pool, env->c->h_stderr[0]); pool_handle(env->c->pool, env->c->h_stderr[3]); /* redirect stdin */ @@ -1493,7 +1548,7 @@ return -1; } - CloseHandle(env->c->h_stdin[1]); + pool_close_handle(env->c->pool, env->c->h_stdin[1]); pool_handle(env->c->pool, env->c->h_stdin[3]); return 0; @@ -1519,45 +1574,17 @@ } /* Close the pipe handle so the child process stops reading. */ - if (!CloseHandle(env->c->h_stdin[3])) + if (!pool_close_handle(env->c->pool, env->c->h_stdin[3])) return -1; env->c->h_stdin[3] = INVALID_HANDLE_VALUE; return 0; } - -int procrun_redirect(char *program, char **envp, procrun_t *env) -{ - STARTUPINFO si; - DWORD id; - - if (!program) { -#ifdef PROCRUN_WINAPP - MessageBox(NULL, "Service not found ", env->m->service.name, - MB_OK | MB_ICONERROR); -#else - fprintf(stderr, "Service not found %s\n", env->m->service.name); -#endif - return -1; - } - memset(&si, 0, sizeof(STARTUPINFO)); - si.cb = sizeof(si); - si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; - - if (procrun_create_pipes(env)) - return -1; - si.hStdOutput = env->c->h_stdout[1]; - si.hStdError = env->c->h_stderr[1]; - si.hStdInput = env->c->h_stdin[0]; - - env->m->envw = make_environment(env->c->env, envp, env->m); - DBPRINTF1("Creating process %s.\n", program); - DBPRINTF1("Creating process %s.\n", env->m->argw); - /* for java.exe merge Arguments and Java options */ - if (env->m->java.jbin) { +static char * set_command_line(procrun_t *env, char *program, int starting){ int i, j, len = strlen(env->m->argw) + 8192; char *opts[64], *nargw; + char *javaClass = starting ? env->m->java.start_class : env->m->java.stop_class, + *javaParam = starting ? env->m->java.start_param : env->m->java.stop_param; j = make_array(env->m->java.opts, opts, 60, env->m); @@ -1565,7 +1592,10 @@ len += strlen(opts[i]); nargw = pool_calloc(env->m->pool, len); - strcpy(nargw, env->m->argw); + if(starting) + strcpy(nargw, env->m->argw); + else + strcpy(nargw, "java"); strcat(nargw, " "); for (i = 0; i < j; i++) { strcat(nargw, opts[i]); @@ -1580,16 +1610,54 @@ else strcat(nargw, program); strcat(nargw, " "); - strcat(nargw, env->m->java.start_class); - if (env->m->java.start_param) { + strcat(nargw, javaClass); + if (javaParam) { strcat(nargw, " "); - strcat(nargw, env->m->java.start_param); + strcat(nargw, javaParam); } env->m->argw = nargw; program = env->m->java.jbin; + return program; +} + +int procrun_redirect(char *program, char **envp, procrun_t *env, int starting) +{ + STARTUPINFO si; + DWORD id; + + if (!program) { +#ifdef PROCRUN_WINAPP + MessageBox(NULL, "Service not found ", env->m->service.name, + MB_OK | MB_ICONERROR); +#else + fprintf(stderr, "Service not found %s\n", env->m->service.name); +#endif + return -1; + } + memset(&si, 0, sizeof(STARTUPINFO)); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + + if(starting) { + if (procrun_create_pipes(env)) + return -1; + si.hStdOutput = env->c->h_stdout[1]; + si.hStdError = env->c->h_stderr[1]; + si.hStdInput = env->c->h_stdin[0]; + } + else + si.dwFlags = STARTF_USESHOWWINDOW; + + env->m->envw = make_environment(env->c->env, envp, env->m); + DBPRINTF1("Creating process %s.\n", program); + DBPRINTF1("Creating process %s.\n", env->m->argw); + /* for java.exe merge Arguments and Java options */ + if (env->m->java.jbin) { + program = set_command_line(env, program, starting); } DBPRINTF2("RUN [%s] %s\n", program, env->m->argw); - if (env->m->service.account && env->m->service.password) { + if (env->m->service.account && env->m->service.password && starting) { HANDLE user, token; DBPRINTF2("RUNASUSER [EMAIL PROTECTED]", env->m->service.account, env->m->service.password); if (!LogonUser(env->m->service.account, @@ -1651,22 +1719,26 @@ return -1; } } - pool_handle(env->c->pool, env->c->pinfo.hThread); - pool_handle(env->c->pool, env->c->pinfo.hProcess); - - SetStdHandle(STD_OUTPUT_HANDLE, env->m->h_stdout[0]); - SetStdHandle(STD_ERROR_HANDLE, env->m->h_stderr[0]); - SetStdHandle(STD_INPUT_HANDLE, env->m->h_stdin[0]); - CloseHandle(env->c->h_stdout[1]); - CloseHandle(env->c->h_stderr[1]); - CloseHandle(env->c->h_stdin[0]); - - CloseHandle(CreateThread(NULL, 0, stdout_thread, env, 0, &id)); - CloseHandle(CreateThread(NULL, 0, stderr_thread, env, 0, &id)); - ResumeThread(env->c->pinfo.hThread); - CloseHandle(CreateThread(NULL, 0, wait_thread, env, 0, &id)); + if(starting) { + pool_handle(env->c->pool, env->c->pinfo.hThread); + pool_handle(env->c->pool, env->c->pinfo.hProcess); + + SetStdHandle(STD_OUTPUT_HANDLE, env->m->h_stdout[0]); + SetStdHandle(STD_ERROR_HANDLE, env->m->h_stderr[0]); + SetStdHandle(STD_INPUT_HANDLE, env->m->h_stdin[0]); + pool_close_handle(env->c->pool, env->c->h_stdout[1]); + pool_close_handle(env->c->pool, env->c->h_stderr[1]); + pool_close_handle(env->c->pool, env->c->h_stdin[0]); + + CloseHandle(CreateThread(NULL, 0, stdout_thread, env, 0, &id)); + CloseHandle(CreateThread(NULL, 0, stderr_thread, env, 0, &id)); + ResumeThread(env->c->pinfo.hThread); + CloseHandle(CreateThread(NULL, 0, wait_thread, env, 0, &id)); - procrun_write_stdin(env); + procrun_write_stdin(env); + } + else + ResumeThread(env->c->pinfo.hThread); return 0; } @@ -1801,6 +1873,9 @@ strcat(path, " " PROC_ARG_RUN_SERVICE); strcat(path, proc->service.name); } + else if (STRNI_COMPARE(argp, PROCRUN_PARAMS_ENVIRONMENT)) { + proc->service.environment = pool_strdup(proc->pool, argv[++i]); + } else { DBPRINTF1("Unrecognized option %s\n", argv[i]); break; @@ -1903,7 +1978,19 @@ set_service_param(proc, PROCRUN_PARAMS_PASSWORD, b, 256, 2); } + + } + if (proc->service.environment) { + int l = strlen(proc->service.environment); + for(i=0; i < l; i++) { + if(proc->service.environment[i] == '#') + proc->service.environment[i] = '\0'; + } + set_service_param(proc, PROCRUN_PARAMS_ENVIRONMENT, + proc->service.environment, 1+2, 0); } + + if (proc->service.startup != SERVICE_NO_CHANGE) set_service_param(proc, PROCRUN_PARAMS_STARTUP, proc->service.startup == SERVICE_AUTO_START ? "auto" : "manual", @@ -1920,7 +2007,6 @@ proc->java.opts, l + 2, 0); } } - static int procrun_install_service(process_t *proc, int argc, char **argv) { SC_HANDLE service; @@ -2136,6 +2222,8 @@ proc->service.account = pool_strdup(proc->pool, argv[++i]); else if (STRNI_COMPARE(argp, PROCRUN_PARAMS_PASSWORD)) proc->service.password = pool_strdup(proc->pool, argv[++i]); + else if (STRNI_COMPARE(argp, PROCRUN_PARAMS_ENVIRONMENT)) + proc->service.environment = pool_strdup(proc->pool, argv[++i]); else break; } @@ -2193,6 +2281,7 @@ return 0; } + static int procrun_delete_service(process_t *proc) { SC_HANDLE service; @@ -2521,6 +2610,7 @@ int service_main(int argc, char **argv) { DWORD fired = 0; + HANDLE jh; int rv = -1; @@ -2546,7 +2636,6 @@ if (g_env->m->java.dll) { if (g_env->m->java.jbin == NULL) { DWORD id; - HANDLE jh; jh = CreateThread(NULL, 0, java_thread, g_env, 0, &id); pool_handle(g_env->m->pool, jh); rv = 0; @@ -2554,13 +2643,13 @@ else { if ((rv = procrun_init_jvm(g_env->m)) == 0) { rv = procrun_redirect(g_env->m->service.image, - g_env->m->envp, g_env); + g_env->m->envp, g_env, 1); } } } else { rv = procrun_redirect(g_env->m->service.image, - g_env->m->envp, g_env); + g_env->m->envp, g_env, 1); } if (rv == 0) { report_service_status(SERVICE_RUNNING, NO_ERROR, 0, @@ -2583,7 +2672,7 @@ DBPRINTF1("Stoping Service %s\n", g_env->m->service.name); report_service_status(SERVICE_STOP_PENDING, NO_ERROR, 3000, g_env->m); - procrun_destroy_jvm(g_env->m); + procrun_destroy_jvm(g_env->m, jh); inject_exitprocess(&g_env->c->pinfo); report_service_status(SERVICE_STOPPED, 0, 0, @@ -2649,6 +2738,19 @@ /* Check if we have a JVM */ if (procrun_load_jvm(env->m, mode) < 0) goto cleanup; + if(env->m->service.environment) { + char *nenv = env->m->service.environment; + while(*nenv) { + char *cenv = pool_strdup(env->c->pool, nenv); + char *equals = strchr(cenv, '='); + if(equals != NULL) { + char *value = nenv + (equals-cenv)+1; + *++equals = '\0'; + procrun_addenv(cenv, value, 0, env->c); + } + nenv += strlen(nenv)+1; + } + } sprintf(event, "PROC_SHUTDOWN_EVENT%d", GetCurrentProcessId()); env->m->events[0] = CreateEvent(NULL, TRUE, FALSE, event); sprintf(event, "PROC_EXITWAIT_EVENT%d", GetCurrentProcessId()); @@ -2746,7 +2848,7 @@ } env->m->service.name = argv[0]; env->m->service.description = argv[2]; - rv = procrun_redirect(argv[2], envp, env); + rv = procrun_redirect(argv[2], envp, env, 1); break; #endif @@ -2754,7 +2856,7 @@ /* Run the process * We can be master or called by env. */ - rv = procrun_redirect(argv[1], envp, env); + rv = procrun_redirect(argv[1], envp, env, 1); break; } @@ -2776,7 +2878,7 @@ if (ac_main_hwnd) ac_show_try_icon(ac_main_hwnd, NIM_DELETE, NULL); #endif - procrun_destroy_jvm(env->m); + procrun_destroy_jvm(env->m, NULL); inject_exitprocess(&env->c->pinfo); i = pool_destroy(env->m->pool); i = pool_destroy(env->c->pool); 1.21 +2 -0 jakarta-commons-sandbox/daemon/src/native/nt/procrun/procrun.h Index: procrun.h =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/daemon/src/native/nt/procrun/procrun.h,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- procrun.h 8 Aug 2003 10:57:13 -0000 1.20 +++ procrun.h 9 Aug 2003 01:59:42 -0000 1.21 @@ -198,6 +198,7 @@ #define PROCRUN_PARAMS_ACCOUNT "User" #define PROCRUN_PARAMS_PASSWORD "Password" #define PROCRUN_PARAMS_INSTALL "Install" +#define PROCRUN_PARAMS_ENVIRONMENT "Environment" /* Console Window position and color */ #define PROCRUN_PARAMS_WINPOS "WindowPosition" #define PROCRUN_PARAMS_WINCLR "WindowColor" @@ -269,6 +270,7 @@ char *image; char *account; char *password; + char *environment; HANDLE infile; HANDLE outfile; HANDLE errfile; 1.12 +34 -27 jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin/procrun.dll <<Binary file>> 1.14 +32 -22 jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin/procrun.exe <<Binary file>> 1.28 +38 -36 jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin/procrunw.exe <<Binary file>> 1.10 +32 -22 jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin/tomcat.exe <<Binary file>> 1.23 +38 -36 jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin/tomcatw.exe <<Binary file>>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]