📄 mtask.c
字号:
/* Make sure */ argc = 0; argv = NULL; dumpTasksAsResponse(command, 0); /* only Java tasks will be listed */ jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "LISTALL")) { /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; dumpTasksAsResponse(command, 1); /* all tasks will be listed */ jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "CHILDREN_EXITED")) { /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; if (childrenExited) { childrenExited = 0; respondWith(command, "YES"); } else { respondWith(command, "NO"); } jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "KILLALL") || !strcmp(argv[0], "KILLEMALL")) {#define KILLALL_SUCCESS "KILL succeeded" killAllTasks(); /* Kill succeeded. Say so */ respondWith(command, KILLALL_SUCCESS); /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "KILL")) { /* KILL a given task */ if (argc != 2) {#define KILL_USAGE "Usage: KILL <taskId>"#define KILL_SUCCESS "KILL succeeded" respondWith(command, KILL_USAGE); } else { char* pidStr = argv[1]; /* Try to convert to integer */ CVMInt32 pid = CVMoptionToInt32(pidStr); if (pid == -1) { /* Bad integer */ respondWith(command, KILL_USAGE); } else if (!killTask(pid)) { /* Kill failed for some reason */ /* Just make a best effort here */ respondWith(command, KILL_USAGE); } else { /* Kill succeeded. Say so */ respondWith(command, KILL_SUCCESS); } } freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "TESTING_MODE")) { /* Set up testing mode, with a file prefix */ if (argc != 2) {#define TESTING_MODE_USAGE "Usage: TESTING_MODE <prefix>"#define TESTING_MODE_SUCCESS "TESTING_MODE succeeded" respondWith(command, TESTING_MODE_USAGE); } else { char* prefix = argv[1]; state->isTestingMode = JNI_TRUE; state->testingModeFilePrefix = strdup(prefix); if (state->testingModeFilePrefix == NULL) { respondWith(command, TESTING_MODE_USAGE); } else { respondWith(command, TESTING_MODE_SUCCESS); } } freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "S")) { /* Always return a response to the connection. */ dumpMessage(command, "SOURCING:"); jumpMessageFree(command); command = NULL; /* In the parent process, setup request and return to caller */ setupRequest(env, argc, argv, 0); /* Make sure */ argc = 0; argv = NULL; /* Who would free up argc and argv? */ return JNI_TRUE; } else if (argv[0][0] != 'J') { /* Not equal to "J*" */ /* If the command is not J, then it is not recognized. */ /* Read next line and re-process. */ respondWith2s(command, "Illegal command \"%s\"", argv[0]); /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } { char* str = oneString(command); fprintf(stderr, "Executing new command: \"%s\"\n", str); free(str); } if (!strcmp(argv[0], "JDETACH")) { amExecutive = CVM_TRUE; } if (!strcmp(argv[0], "JNATIVE")) { /* Run native process (driver) */ TaskRec* task;#define JNATIVE_USAGE "Usage: JNATIVE <proc_name> <lib_name> [<proc_args>...]" if (argc < 3) { respondWith(command, JNATIVE_USAGE); freeArgs(argc, argv); argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } /* try to figure out if the process is already run. * The task command should start with "JNATIVE <procName>..." */ for (task = taskList; task != NULL; task = task->next) { int len = strlen(argv[1]); /* argv[1] == procName */ if (task->procType == PROCTYPE_NATIVE && !strncmp(task->command, "JNATIVE ", 8) && !strncmp(task->command+8, argv[1], len) && (task->command[8+len] == '\0' || task->command[8+len] == ' ')) { break; } } if (task != NULL) { /* process has been found in the taskList * We don't have to run it */ respondWith2(command, "CHILD PID=%d", task->pid); freeArgs(argc, argv); argc = 0; argv = NULL; jumpMessageFree(command); command = readRequestMessage(); continue; } }#if 0 /* How to do sync? */ if (!strcmp(argv[0], "JSYNC")) { isSync = CVM_TRUE; }#endif#if 1 { int j; for(j = 0; j < argc; j++) { fprintf(stderr, "\tARGV[%d] = \"%s\"\n", j, argv[j]); } }#endif /* Fork off a process, and handle the request */ if ((pid = fork()) == 0) { int mypid = getpid(); /* Remember the pid of our process for compatibility with non-Posix compliant systems on which getpid() returns a thread id. */ jumpProcessSetId(mypid); /* Make sure each launched process knows the id of the executive */ if (amExecutive) { jumpProcessSetExecutiveId(mypid); } else { jumpProcessSetExecutiveId(executivePid); } /* Child process */#ifdef CVM_TIMESTAMPING if (!CVMmtaskTimeStampReinitialize(env)) { fprintf(stderr, "Could not reinitialize timestamping, exiting\n"); exit(1); }#endif /* Make sure all the fd's we inherit from the parent get freed up */ closeAllFdsExcept(-1); if (state->isTestingMode) { char* prefix = state->testingModeFilePrefix; /* We want to open files for stdout and stderr */ int outfd = createLogFile(prefix, "stdout", mypid); int errfd = createLogFile(prefix, "stderr", mypid); if ((outfd == -1) || (errfd == -1)) { /* Due to some error that was reported in createLogFile() */ fprintf(stderr, "MTASK: Could not set debug mode\n"); } else { /* Hook up stdout and stderr in the child process to the right files */ dup2(outfd, 1); dup2(errfd, 2); close(outfd); close(errfd); } } #if 0 /* how to do sync? */ else if (isSync) { /* If we are in JSYNC execution, route stdout and stderr back where the request came from */ dup2(connfd, 1); dup2(connfd, 2); }#endif if (!strcmp(argv[0], "JNATIVE")) { /* we are launching a native process */ if ((nativeMain = prepareJNative(argv[1], argv[2])) == NULL) { respondWith(command, JNATIVE_USAGE); jumpMessageFree(command); freeArgs(argc, argv); argc = 0; argv = NULL; exit(1); } } /* First, make sure that the child PID is communicated to the client connection. */ respondWith2(command, "CHILD PID=%d", mypid); /* No need for the connections in the child */ jumpMessageFree(command); if (nativeMain != NULL) { /* call 'main' of the native process */ (*nativeMain)(argc, argv); /* free anything after the process finished */ freeArgs(argc, argv); argc = 0; argv = NULL; exit(0); /* return from the native process */ } /* We need these threads in the child */ if (!restartSystemThreads(env, state)) { exit(1); } /* In the child process, setup request and return to caller */ setupRequest(env, argc, argv, mypid); /* Make sure */ argc = 0; argv = NULL; return JNI_FALSE; } else if (pid == -1) { amExecutive = CVM_FALSE; perror("Fork"); freeArgs(argc, argv); jumpMessageFree(command); } else { amExecutive = CVM_FALSE; fprintf(stderr, "SPAWNED OFF PID=%d\n", pid); /* Add this new task into our "database" unless launching via JDETACH */ if (!strcmp(argv[0], "JDETACH")) { /* Remember this as a special pid. */ executivePid = pid; if (state->isTestingMode) { executiveTestingModeFilePrefixSnapshot = strdup(state->testingModeFilePrefix); } } else { /* add task to the task list */ addTask(env, state, pid, oneString(command), (strcmp(argv[0], "JNATIVE") ? PROCTYPE_JAVA : PROCTYPE_NATIVE)); } jumpMessageFree(command); /* The child is executing this command. The parent can free the arguments */ /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv); /* Don't free 'command' here, since it's been put in the task structure. We'll free it when we free the task */#if 0 /* Is there a good way to do sync? */ if (isSync) { /* Wait for child to exit */ int status = doReapChildren(state, 0); printExitStatusString(connfp, status); isSync = CVM_FALSE; /* This being a sync call, blow the caller off. */ command = NULL; continue; }#endif } command = readRequestMessage(); } /* fprintf(stderr, "Quitting this connection, waiting for new one\n"); */ } jumpMessageShutdown(); /* Parent exits? Should sleep until the last child exits */ exit(0);}intMTASKnextRequest(ServerState *state){ JNIEnv *env = state->env; /* Any other server specific initialization goes here */ /* Sleep waiting for a request. The client process returns here, while the parent goes back to sleep. */ /* There is one exception to this, and that is the "SOURCE" command. This allows the server to execute a program in its own address space rather than a child's, allowing it to expand its state */ state->wasSourceCommand = waitForNextRequest(env, state); if (state->wasSourceCommand) { /* Prepare to process any weakrefs emerging from this command */ if (!restartSystemThreads(env, state)) { return 0; } } return 1;}voidMTASKserverSourceReset(ServerState *state){ /* Clear sun.misc.CVM's notion of what the main class was */ (*state->env)->CallStaticVoidMethod(state->env, state->cvmClass, state->resetMainID); /* And stop threads */ stopSystemThreads(state);}intMTASKserverInitialize(ServerState* state, CVMParsedSubOptions* serverOpts, JNIEnv* env, jclass cvmClass){ const char* clist = CVMgetParsedSubOption(serverOpts, "initClasses"); const char* mlist = CVMgetParsedSubOption(serverOpts, "precompileMethods"); /* Remember the pid of our process for compatibility with non-Posix compliant systems on which getpid() returns a thread id. */ jumpProcessSetId(getpid()); jumpMessageStart(); { /* FIXME: check the return code. */ JUMPMessageStatusCode code; jumpMessageRegisterDirect("mvm/server", &code); } /* Create a non-blocking pipe for child() to notify the main loop. */ { int pipes[2]; int i; if (pipe(pipes) == -1) { goto error; } for ( i = 0; i < 2; i++) { int fl; fl = fcntl(pipes[i], F_GETFL); if (fl == -1) { goto error; } fl |= O_NONBLOCK; if (fcntl(pipes[i], F_SETFL, fl) == -1) { goto error; } } child_pipe_read = pipes[0]; child_pipe_write = pipes[1]; } message_fd = jumpMessageGetFd("mvm/server"); if (message_fd == -1) { goto error; } /* * Set these up while server is being initialized. * This way we don't have to look up these JNI ID's again. */ state->referenceClass = (*env)->FindClass(env, "java/lang/ref/Reference"); assert(state->referenceClass != NULL); state->restartSystemThreadsID = (*env)->GetStaticMethodID(env, state->referenceClass, "restartReferenceThreads", "()V"); assert(state->restartSystemThreadsID != NULL); state->stopSystemThreadsID = (*env)->GetStaticMethodID(env, state->referenceClass, "stopReferenceThreads", "()V"); assert(state->stopSystemThreadsID != NULL); { struct sigaction sa; sa.sa_handler = child; sa.sa_flags = SA_RESTART;#ifdef SA_NOCLDSTOP sa.sa_flags |= SA_NOCLDSTOP;#endif sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); } { extern void jumpProcessSetServerPid(int); jumpProcessSetServerPid(getpid()); } fprintf(stderr, "Starting mTASK server at pid=%d .... ", getpid()); state->env = env; state->cvmClass = cvmClass; state->initialized = JNI_TRUE; state->isTestingMode = JNI_FALSE; state->testingModeFilePrefix = NULL; /* * Now let's warmup. Make sure we do this before stopSystemThreads(), * because stopSystemThreads() will also close all open fd's. We need the * fd's, becuase we may need to load classes. */ if (clist != NULL || mlist != NULL) { jclass warmupClass; jmethodID runitID; jstring jclist; jstring jmlist; warmupClass = (*env)->FindClass(env, "sun/mtask/Warmup"); if (warmupClass == NULL) { goto error; } runitID = (*env)->GetStaticMethodID(env, warmupClass, "runit", "(Ljava/lang/String;Ljava/lang/String;)V"); if (runitID == NULL) { goto error; } jclist = (clist == NULL) ? NULL : (*env)->NewStringUTF(env, clist); if ((*env)->ExceptionOccurred(env)) { goto error; } jmlist = (mlist == NULL) ? NULL : (*env)->NewStringUTF(env, mlist); if ((*env)->ExceptionOccurred(env)) { goto error; } (*env)->CallStaticVoidMethod(env, warmupClass, runitID, jclist, jmlist); } stopSystemThreads(state); fprintf(stderr, "done!\n"); state->resetMainID = (*env)->GetStaticMethodID(env, cvmClass, "resetMain", "()V"); if (state->resetMainID == NULL) { goto error; } CVMdestroyParsedSubOptions(serverOpts); return 1;error: CVMdestroyParsedSubOptions(serverOpts); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -