📄 mtask.c
字号:
return result;}static voidcloseAllFdsExcept(int fd){ /* nothing to do */}static intnumberOfTasks(){ int num = 0; TaskRec* task; for (task = taskList; task != NULL; task = task->next) { num++; } return num; }/* * multi-string response to caller, packaged as * return message. * all == 0 if only Java tasks is being listed */static voiddumpTasksAsResponse(JUMPMessage command, int all){ JUMPOutgoingMessage m; JUMPMessageStatusCode code; JUMPMessageMark mark; JUMPMessageMark eom; TaskRec* task; int numTasks = 0; m = jumpMessageNewOutgoingByRequest(command, &code); jumpMessageMarkSet(&mark, m); jumpMessageAddInt(m, numTasks); for (task = taskList; task != NULL; task = task->next) { if (all || task->procType == PROCTYPE_JAVA) { dumpTaskIntoMessage(m, task); /* Brief printout to caller */ dumpTaskOne(task); /* Verbose printout to console */ numTasks ++; } } jumpMessageMarkSet(&eom, m); jumpMessageMarkResetTo(&mark, m); jumpMessageAddInt(m, numTasks); jumpMessageMarkResetTo(&eom, m); jumpMessageSendAsyncResponse(m, &code);}/* * pthread's will not survive across a fork. Therefore, allow stopping * and re-starting of system threads for sanity across app launching. */static voidstopSystemThreads(ServerState* state){ jclass referenceClass; jmethodID stopMethod; JNIEnv *env = state->env; referenceClass = state->referenceClass; stopMethod = state->stopSystemThreadsID; /* * Call sun.misc.ThreadRegistry.waitAllSystemThreadsExit() * to shutdown system threads */ (*env)->CallStaticVoidMethod(env, referenceClass, stopMethod); if ((*env)->ExceptionOccurred(env)) { /* * Ignore and clear the exception */ CVMconsolePrintf("Exception occurred during " "ThreadRegistry.waitAllSystemThreadsExit()\n"); (*env)->ExceptionDescribe(env); return; } /* Shut down the fd's of any zip files we've cached. We can't fork with open fd's. */ ZIP_Closefds();#if defined(CVM_HAVE_DEPRECATED) || defined(CVM_THREAD_SUSPENSION) CVMmtaskHandleSuspendChecker();#endif}static jbooleanrestartSystemThreads(JNIEnv* env, ServerState* state){ jclass referenceClass; jmethodID restartMethod; /* Ready to execute code, so re-open cached zip fd's */ if (!ZIP_Reopenfds()) { return JNI_FALSE; } referenceClass = state->referenceClass; restartMethod = state->restartSystemThreadsID; /* * Call sun.misc.ThreadRegistry.waitAllSystemThreadsExit() * to shutdown system threads */ (*env)->CallStaticVoidMethod(env, referenceClass, restartMethod); if ((*env)->ExceptionOccurred(env)) { /* * Ignore and clear the exception */ CVMconsolePrintf("Exception occurred during " "java.lang.ref.Reference.restartSystemThreads()\n"); (*env)->ExceptionDescribe(env); return JNI_FALSE; } return JNI_TRUE;}static voiddumpMessage(JUMPMessage m, char* intro){ JUMPMessageReader r; JUMPPlatformCString* strings; uint32 len, i; jumpMessageReaderInit(&r, m); strings = jumpMessageGetStringArray(&r, &len); printf("%s\n", intro); for (i = 0; i < len; i++) { printf(" \"%s\"\n", strings[i]); }}static char*oneString(JUMPMessage m){ JUMPMessageReader r; JUMPPlatformCString* strings; uint32 len; jumpMessageReaderInit(&r, m); strings = jumpMessageGetStringArray(&r, &len); if (r.status != JUMP_SUCCESS) { return NULL; } if (strings != NULL) { uint32 i; uint32 bufSize = 1; /* for the string null terminator */ char* string; /* first figure out the size of the buffer we need to allocate */ for (i = 0; i < len; i++) { if (strings[i] != NULL) { bufSize += strlen(strings[i]) + 1 /* for the " " */; } } /* allocate the buf and start copying */ string = calloc(bufSize, sizeof(char)); if (string != NULL) { for (i = 0; i < len; i++) { if (strings[i] != NULL) { strcat(string, strings[i]); strcat(string, " "); } } } jumpMessageFreeStringArray(strings, len); return string; } else { return calloc(1, sizeof(char)); }}/* Returns a JUMPMessage when there is a message to process. There may also be children to deal with. Returns (JUMPMessage)-1 when there is no message but there may be children to deal with. Returns NULL on error. */static JUMPMessagereadRequestMessage(){ fd_set readfds; /* Wait for a possible message or a child notification, or abort on error. */ while (1) { int fds; int status; FD_ZERO(&readfds); fds = 0; FD_SET(message_fd, &readfds); if (message_fd > fds) { fds = message_fd; } FD_SET(child_pipe_read, &readfds); if (child_pipe_read > fds) { fds = child_pipe_read; } status = select(fds + 1, &readfds, NULL, NULL, NULL); if (status == -1) { if (errno == EINTR) { continue; } return NULL; } if (status == 0) { continue; } break; } if (FD_ISSET(child_pipe_read, &readfds)) { /* Clear bytes from the pipe. */ while (1) { /* 24 is just a smallish buffer size; there's nothing special about it. Since we read in a loop it could be 1, but using a slightly larger buffer allows us to read multiple bytes at once, should there be any. */ char buffer[24]; int status = read(child_pipe_read, buffer, sizeof(buffer)); if (status == -1) { if (errno == EINTR) { continue; } if (errno == EAGAIN) { break; } return NULL; } if (status == 0) { /* EOF, this should never happen, something is broken. */ return NULL; } } } if (FD_ISSET(message_fd, &readfds)) { JUMPMessage in; JUMPMessageStatusCode code; /* There's a message so this should not block. */ in = jumpMessageWaitFor("mvm/server", 0, &code); if (in != NULL) { dumpMessage(in, "Server received:"); } return in; } return (JUMPMessage) -1;}/* * Uniform response message from server to caller. * Always a string array for now */static voidrespondWith(JUMPMessage command, char* str){ JUMPOutgoingMessage m; JUMPMessageStatusCode code; JUMPPlatformCString strs[1]; m = jumpMessageNewOutgoingByRequest(command, &code); strs[0] = (JUMPPlatformCString)str; jumpMessageAddStringArray(m, strs, 1); jumpMessageSendAsyncResponse(m, &code);}static voidrespondWith2(JUMPMessage command, char* format, int v){ char str[256]; snprintf(str, 256, format, v); respondWith(command, str);}static voidrespondWith2s(JUMPMessage command, char* format, char* arg){ char str[256]; snprintf(str, 256, format, arg); respondWith(command, str);}static voidtokenizeArgs(JUMPMessage m, int* argc, char*** argv){ JUMPMessageReader r; JUMPPlatformCString* strings; uint32 len; jumpMessageReaderInit(&r, m); strings = jumpMessageGetStringArray(&r, &len); *argc = len; *argv = (char**)strings;}/* * Make some preparations for launching a native process: * 1) Load a shared library (if needed). * 2) Find a symbol in the shared library. * 3) Create incoming message queue. * Returns NULL in case of error, the address of the symbol otherwise */static void *prepareJNative(char *procName, char *soLibName){ void *dsoHandle; char *libName; JUMPMessageQueueStatusCode code = 0; unsigned char *type; void *symbol = NULL; /* * trying to find native method. * If the lib name is "main" then * we have to look for the symbol * in the main binary module. */ if (strcmp(soLibName, "main")) { /* making a library name */ libName = malloc(strlen(soLibName) + 3 /*lib*/ + 3 /*.so*/ +#ifdef CVM_DEBUG 2 /*_g*/ +#endif 1 /*'\0'*/); if (libName == NULL) { fprintf(stderr, "MTASK: No memory for lib name\n"); return NULL; } strcpy(libName, "lib"); strcat(libName, soLibName);#ifdef CVM_DEBUG strcat(libName, "_g");#endif strcat(libName, ".so"); dsoHandle = dlopen(libName, RTLD_LAZY); free(libName); if (dsoHandle != NULL) { symbol = dlsym(dsoHandle, procName); /* FIXME: should we do "dlclose()" somewhere? */ } } if (symbol == NULL) { symbol = dlsym(RTLD_DEFAULT, procName); } if (symbol == NULL) { /* method hasn't been found */ fprintf(stderr, "MTASK: Can't find symbol '%s' in library %s\n", procName, soLibName); return NULL; }#define MSGPREFIX_NATIVE "native" /* * creating the message queue for our process. * It must be created before the launcher received * successful result */ /* allocate memory for queue's name */ type = malloc(strlen(MSGPREFIX_NATIVE) + 2 + strlen(procName)); if (type == NULL) { fprintf(stderr, "MTASK: No memory for queue name\n"); return NULL; } /* making queue name */ strcpy((char*)type, (char*)MSGPREFIX_NATIVE); strcat((char*)type, "/"); strcat((char*)type, procName); /* we trying to create a queue named "native/<procName>" */ jumpMessageQueueCreate(type, &code); if (code != JUMP_MQ_SUCCESS) { fprintf(stderr, "MTASK: Can't create message queue %s\n", type); free(type); return NULL; } free(type); return symbol;}/* * A JVM server. Sleep waiting for new requests. As new ones come in, * fork off a process to handle each and go back to sleep. * * return JNI_FALSE if a fork'ed child executes a request. * return JNI_TRUE if the parent sources the command */static jbooleanwaitForNextRequest(JNIEnv* env, ServerState* state){ JUMPMessage command = NULL; CVMBool done; int childrenExited = 0; /* No one has exited yet */ done = CVM_FALSE; /* * Set up the networking for the server * It might have been initialized already, in which case don't * touch the fd that was passed in. */ assert(state->initialized); while (!done) { int argc; char** argv; int pid; /* Accepted a connection. Now accept commands from this connection */ command = readRequestMessage(); while (command != NULL) { /* local variable that will keep pointer to native's main() */ void (*nativeMain)(int argc, char **argv) = NULL; /* * Check for children to reap before each command * is executed */ while (reapChildrenFlag) { /* Remember we have detected dead children */ childrenExited = 1; reapChildren(state); } if (command == (JUMPMessage) -1) { /* There was no message, just a child notification. */ command = readRequestMessage(); continue; } tokenizeArgs(command, &argc, &argv); if (!strcmp(argv[0], "JEXIT")) { respondWith(command, "YES"); jumpMessageShutdown(); /* Simply exit here. That's what JEXIT is supposed to do. */ exit(0); } else if (!strcmp(argv[0], "SETENV")) { /* set environment variable */ if (argc != 2) {#define SETENV_USAGE "Usage: SETENV <keyValuePair>"#define SETENV_SUCCESS "SETENV succeeded" respondWith(command, SETENV_USAGE); } else { char* pair; pair = strdup(argv[1]); if (pair == NULL) { /* setenv failed */ respondWith(command, SETENV_USAGE); } else { char* name = pair; char* value = strchr(pair, '='); if (value == NULL) { /* setenv failed */ respondWith(command, SETENV_USAGE); } else { *value = '\0'; value++; fprintf(stderr, "setenv(%s, %s)\n", name, value); if (*value == '\0') { /* unsetenv */#ifdef __linux__ unsetenv(name);#else value[-1] = '='; putenv(name);#endif /* setenv succeeded */ respondWith(command, SETENV_SUCCESS); } else { /* setenv */#ifdef __linux__ if (setenv(name, value, 1) == 0) {#else value[-1] = '='; if (putenv(name) == 0) {#endif /* setenv succeeded */ respondWith(command, SETENV_SUCCESS); } else { /* setenv failed */ respondWith(command, SETENV_USAGE); } } } } } /* The man page does not say whether setenv makes a copy of the arguments. So I don't know whether I can free the strdup'ed argv[1]. Be conservative and retain it here. */ freeArgs(argc, argv); /* Make sure */ argc = 0; argv = NULL; free(command); command = readRequestMessage(); continue; } else if (!strcmp(argv[0], "LIST")) { /* Don't forget to free up all the (argc, argv[]) mem. */ freeArgs(argc, argv);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -