⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mtask.c

📁 This is a resource based on j2me embedded,if you dont understand,you can connection with me .
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * @(#)mtask.c	1.37 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <string.h>#include <sys/types.h>#include <fcntl.h>#include <signal.h>#include <unistd.h>#include <sys/time.h>#include <sys/resource.h>#include <sys/wait.h>#include <sys/select.h>#include <errno.h>#include "javavm/export/jni.h"#include "javavm/export/cvm.h"#include "portlibs/ansi_c/java.h"#include "portlibs/posix/mtask.h"#include <jump_messaging.h>#include <dlfcn.h>#include "porting/JUMPMessageQueue.h"#include "porting/JUMPProcess.h"#include "zip_util.h"/* A non-blocking pipe that child() uses to notify the main loop. */static int child_pipe_write;static int child_pipe_read;/* Fd that main loop messages will arrive on. */static int message_fd;/* * Free (argc, argv[]) set */static voidfreeArgs(int argc, char** argv){    int i;    for (i = 0; i < argc; i++) {	if (argv[i] != NULL) {	    free(argv[i]);	    argv[i] = NULL;	}    }    free(argv);}static voidsetupRequest(JNIEnv*env, int argc, char** argv, CVMInt32 clientId){    char* appclasspathStr = NULL;    char* bootclasspathStr = NULL;    JavaVMInitArgs* clientArgs;    char* parse;    int cpadd;    clientArgs = ANSIargvToJinitArgs(argc - 1, argv + 1, 				     &appclasspathStr,				     &bootclasspathStr);    /* Now take this set of init args, and parse them */    parse = CVMparseCommandLineOptions(env, clientArgs, clientArgs->nOptions);    if (parse != NULL) {	/* If the parse failed for some reason, the parser must have already	   printed out the necessary message on the console. Exit with an	   error code. */	fprintf(stderr, "Exiting JVM\n");	exit(1);    }    /* The JVM state now reflects the arguments. Also amend the classpath       setting with the value that we read from appclasspathStr and       bootclasspathStr */    cpadd = CVMclassClassPathAppend(env, appclasspathStr, bootclasspathStr);    if (!cpadd) {	/* If the class path add failed for some reason, the system must have	   already printed out the necessary message on the console. Exit with	   an error code. */	fprintf(stderr, "Exiting JVM\n");	exit(1);    }    /* Initialize child VM */    CVMmtaskReinitializeChildVM(env, clientId);    /* Free up the (argc,arv[]) and jInitArgs that we have built */    ANSIfreeJinitArgs(clientArgs);    freeArgs(argc, argv);    /* Now we are ready to execute code */#ifdef CVM_TIMESTAMPING    if (clientId != 0) {	CVMmtaskTimeStampRecord(env, "Child Created", -1);    }#endif}static void child(int sig);/* * Task management  */typedef enum _ProcType {    PROCTYPE_JAVA = 1,    PROCTYPE_NATIVE} ProcType;typedef struct _TaskRec {    int pid;    char* command;    /* is it a native process or JVM? */    ProcType procType;    /* testing mode specific snapshot of prefix */    char* testingModeFilePrefixSnapshot;    struct _TaskRec* next;    /* Any other task info? */} TaskRec;/* Single process for the mtask server, so these globals are OK */static int numTasks = 0;static TaskRec* taskList = NULL;static volatile int reapChildrenFlag = 0;static int executivePid = -1;static int amExecutive = 0;static char* executiveTestingModeFilePrefixSnapshot = NULL;/* * Handle exiting children so they don't hang around as zombies. */static void child(int sig){    int pid = getpid();    char buffer = 'A';    fprintf(stderr, "Received SIGCHLD in PID=%d\n", pid);    reapChildrenFlag = 1;    /* Non-blocking write, just ignore any error. */    write(child_pipe_write, &buffer, 1);}static void dumpTaskOneWithFp(TaskRec* task, FILE *fp, int verbose){    if (verbose) {	fprintf(fp, 		 "[Task pid=%d, command=\"%s\"(0x%x)]\n",		 task->pid, task->command, 		 (unsigned int)task->command);    } else {	fprintf(fp, "PID=%d COMMAND=\"%s\"\n", task->pid, task->command);    }}static void dumpTaskIntoMessage(JUMPOutgoingMessage m, TaskRec* task){    char str[256];        snprintf(str, 256, "PID=%d COMMAND=\"%s\"", task->pid, task->command);    jumpMessageAddString(m, str);}static voiddumpTaskOne(TaskRec* task){    // Verbose printout on stderr    dumpTaskOneWithFp(task, stderr, 1);}static voidfreeTask(TaskRec* task){    fprintf(stderr, "FREEING TASK: ");    dumpTaskOne(task);        free(task->command);    if (task->testingModeFilePrefixSnapshot != NULL) {	free(task->testingModeFilePrefixSnapshot);    }    free(task);    numTasks--;}/* * Find TaskRec corresponding to given pid */static TaskRec* findTaskFromPid(int taskPid){    TaskRec* task;    for (task = taskList; task != NULL; task = task->next) {	if (task->pid == taskPid) {	    return task;	}    }    return NULL;}/* * removeTask with a given pid * * Called after the SIGCHLD signal handler signaled that there are * children exiting */static voidremoveTask(int taskPid){    TaskRec* task;    TaskRec* taskPrev = NULL;    for (task = taskList; task != NULL; taskPrev = task, task = task->next) {	if (task->pid == taskPid) {	    if (taskPrev == NULL) {		/* The first item in the list */		taskList = task->next;	    } else {		taskPrev->next = task->next;	    }	    freeTask(task);	    return;	}    }}/* * Create log file off of 'prefix', named 'kind' for 'pid' * Return fd */static intcreateLogFile(char* prefix, char* kind, int pid){    /* We want to open files for stdout, stderr, and exit       codes. */    int prefixLen = strlen(prefix) + 1;    const int maxPidLen = 6;    const int kindLength = strlen(kind) + 1;    const int maxFileLen = 	prefixLen +	maxPidLen +	kindLength;    char* fileName = calloc(1, maxFileLen);    int fd;    if (fileName == NULL) {	fprintf(stderr, "Out of memory trying to open log file %s\n",		fileName);	return -1;    }    sprintf(fileName, "%s/%s.%d", prefix, kind, pid);    /*fprintf(stderr, "%s fileName = %s\n", kind, fileName);*/    fd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0666);    if (fd == -1) {	perror(fileName);    }    return fd;}static FILE*makeLineBufferedStream(int socket){    FILE* stream;    stream = fdopen(socket, "w");    if (stream != NULL) {	setvbuf(stream, NULL, _IOLBF, BUFSIZ);    }    return stream;}    static voidprintExitStatusString(FILE* out, int status){    if (WIFEXITED(status)) {	fprintf(out, "<exit code %d>\n", WEXITSTATUS(status));    } else if (WIFSIGNALED(status)) {	fprintf(out, "<uncaught signal %d>\n", WTERMSIG(status));    } else if (WIFSTOPPED(status)) {	fprintf(out, "<stopped with signal %d>\n", WSTOPSIG(status));    } } /*  * Send executive a lifecycle message indicating that a child has terminated.  */static voidnotifyTermination(int cpid) {    JUMPOutgoingMessage message;    JUMPAddress executiveAddr;    JUMPMessageStatusCode statusCode;    message = jumpMessageNewOutgoingByType("mvm/lifecycle", &statusCode);    jumpMessageAddString(message, "IsolateDestroyed"); /* ID_ISOLATE_DESTROYED */    jumpMessageAddInt(message, 0); /* String[] data length */    jumpMessageAddInt(message, cpid); /* isolateId */    jumpMessageAddInt(message, 0);    /* appID */    executiveAddr.processId = executivePid;    jumpMessageSendAsync(executiveAddr, message, &statusCode);    jumpMessageFreeOutgoing(message);}/* * The signal handler indicated there are children to reap. Do it. * Return last status reaped. */static intdoReapChildren(ServerState* state, int options){    int cpid, status;    struct rusage ru;    /* Reset the flag early. If the signal handler re-raises this, we will       discover this in the next iteration of reapChildren() */    reapChildrenFlag = 0;    while ((cpid = wait3(&status, options, &ru)) > 0) {	int exitcodefd;        /* Notify the executive about the isolate termination */	if (cpid != executivePid) {           notifyTermination(cpid);	} 	/* This had better be one of ours */	assert((executivePid == cpid) || (findTaskFromPid(cpid) != NULL));	fprintf(stderr, "Reaping child process %d\n", cpid);	jumpMessageQueueCleanQueuesOf(cpid);		printExitStatusString(stderr, status);	fprintf(stderr, "\t user time %ld.%02d sec\n",		ru.ru_utime.tv_sec,		(int)(ru.ru_utime.tv_usec / 1000 / 10));	fprintf(stderr, "\t sys time %ld.%02d sec\n",		ru.ru_stime.tv_sec,		(int)(ru.ru_stime.tv_usec / 1000 / 10));	fprintf(stderr, "\t max res set %ld\n",		ru.ru_maxrss);#if 0	fprintf(stderr, "\t integral shared mem size %ld\n",		ru.ru_ixrss);	fprintf(stderr, "\t integral unshared data size %ld\n",		ru.ru_idrss);	fprintf(stderr, "\t integral unshared stack size %ld\n",		ru.ru_isrss);#endif	fprintf(stderr, "\t page reclaims (minor faults) %ld\n",		ru.ru_minflt);	fprintf(stderr, "\t page faults (major) %ld\n",		ru.ru_majflt);	fprintf(stderr, "\t swaps %ld\n",		ru.ru_nswap);#if 0	fprintf(stderr, "\t block input operations %ld\n",		ru.ru_inblock);	fprintf(stderr, "\t block output operations %ld\n",		ru.ru_oublock);#endif	if (state->isTestingMode) {	    TaskRec* task = findTaskFromPid(cpid);	    char* testingModeFilePrefixSnapshot;	    	    /* Now make a record, but only if TESTING_MODE was executed	       _prior_ to launching this currently reaped task. We can't	       apply current testing mode to an app that did not know	       about it */	    if (executivePid == cpid) {		testingModeFilePrefixSnapshot = 		    executiveTestingModeFilePrefixSnapshot;	    } else {		testingModeFilePrefixSnapshot = 		    task->testingModeFilePrefixSnapshot;	    }	    if (testingModeFilePrefixSnapshot != NULL) {		/* Use the snapshot of the file prefix created at launch */		exitcodefd = createLogFile(testingModeFilePrefixSnapshot,					   "exitcode", cpid);		if (exitcodefd == -1) {		    perror("exitcodefile");		} else {		    FILE* exitcodefile = makeLineBufferedStream(exitcodefd);		    printExitStatusString(exitcodefile, status);		    fclose(exitcodefile);		    close(exitcodefd);		}	    }	}	if (executivePid == cpid) {	    /* Get rid of all traces */	    executivePid = -1;	    if (executiveTestingModeFilePrefixSnapshot != NULL) {		free(executiveTestingModeFilePrefixSnapshot);		executiveTestingModeFilePrefixSnapshot = NULL;	    }	} else {	    removeTask(cpid);	}    }    return status;}static voidreapChildren(ServerState* state){    doReapChildren(state, WNOHANG);}/* * A new task has been created  */static intaddTask(JNIEnv* env, ServerState* state, int taskPid, char* command,        ProcType type){    TaskRec* task;    task = (TaskRec*)calloc(1, sizeof(TaskRec));    if (task == NULL) {	return JNI_FALSE;    }    task->pid = taskPid;    task->command = command;    task->procType = type;    /* Take a snapshot of the testing mode prefix here */    if (state->isTestingMode) {	task->testingModeFilePrefixSnapshot =	    strdup(state->testingModeFilePrefix);	if (task->testingModeFilePrefixSnapshot == NULL) {	    fprintf(stderr, "Could not allocate file prefix snapshot\n");	    free(task->command);	    free(task);	    return JNI_FALSE;	}    } else {	task->testingModeFilePrefixSnapshot = NULL;    }#if 0    fprintf(stderr, "Added task=0x%x: [pid=%d, \"%s\"(0x%x)]\n",	    task, taskPid, task->command, (unsigned int)task->command);#endif    numTasks++;    /* Insert at the head */    task->next = taskList;    taskList = task;    return JNI_TRUE;}static CVMBoolkillTaskFromTaskRec(TaskRec* task){#if 0    /*     * Message based exit     * Not so robust, so commenting out for now.     */    return sendMessageToTask(task, "EXIT");#else    if (kill(task->pid, SIGKILL) == -1) {	perror("kill");	return CVM_FALSE;    }    /* Killing is "best effort" and needs to be verified via       Java, preferably using Xlet.getState() api's */    return CVM_TRUE;#endif}static CVMBoolkillTask(int taskPid){    TaskRec* task;    task = findTaskFromPid(taskPid);    if (task == NULL) {	return CVM_FALSE;    }    return killTaskFromTaskRec(task);}static CVMBoolkillAllTasks(){    TaskRec* task;    CVMBool result = CVM_TRUE;        for (task = taskList; task != NULL; task = task->next) {	if (!killTaskFromTaskRec(task)) {	    result = CVM_FALSE;	}    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -