You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by bi...@apache.org on 2003/08/09 03:59:42 UTC
cvs commit: jakarta-commons-sandbox/daemon/src/native/nt/procrun/bin procrun.dll procrun.exe procrunw.exe tomcat.exe tomcatw.exe
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 %s@%s\n", 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: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org