예제 #1
0
int my_entrance()
{
    if (fork_syscall() == 0) {
        // son
        while(1) {
            print_char('S');
        }
    } else {
        // dad
        while(1) {
            print_char('D');
        }
    }
    return 0;
}
예제 #2
0
void
stackdump(void)
{
    int pid, core_pid;
    /* get name now -- will be same for children */
    char *exec_name = get_application_name();
    char core_name[128];
    char tmp_name[128];
    snprintf(tmp_name, 128, "%s.%d", TEMPORARY_FILENAME, get_process_id());

#ifdef VMX86_SERVER
    if (os_in_vmkernel_userworld()) {
        return; /* no local gdb, no multithreaded fork */
    }
#endif

#if VERBOSE
    SYSLOG_INTERNAL_ERROR("about to fork parent %d to dump core", get_process_id());
#endif

    /* Fork a child to dump core */
    pid = fork_syscall();
    if (pid == 0) { /* child */
#if VERBOSE
        SYSLOG_INTERNAL_ERROR("about to dump core in process %d parent %d thread " TIDFMT
                              "",
                              get_process_id(), get_parent_id(), get_thread_id());
#endif
        /* We used to use abort here, but that had lots of complications with
         * pthreads and libc, so now we just dereference NULL.
         */
        if (!set_default_signal_action(SIGSEGV)) {
            SYSLOG_INTERNAL_ERROR("ERROR in setting handler");
            exit_process_syscall(1);
        }
        *(volatile int *)NULL = 0;
#if VERBOSE
        SYSLOG_INTERNAL_ERROR("about to exit process %d", get_process_id());
#endif
        exit_process_syscall(0);
    } else if (pid == -1) {
        SYSLOG_INTERNAL_ERROR("ERROR: could not fork to dump core");
        exit_process_syscall(1);
    }
#if VERBOSE
    SYSLOG_INTERNAL_ERROR("parent %d %d waiting for child %d", get_process_id(),
                          get_thread_id(), pid);
#endif
    /* Parent continues */
    core_pid = pid;
    while (wait_syscall(NULL) != pid) {
        /* wait for core to be dumped */
    }

#if VERBOSE
    SYSLOG_INTERNAL_ERROR("about to fork 2nd child to run gdb");
#endif
    /* Fork a 2nd child to run gdb */
    pid = fork_syscall();
    if (pid == 0) { /* child */
        file_t fp;
        int fd;
        const char *argv[16];
        int i;
        int execve_errno;

        /* Open a temporary file for the input: the "where" command */
        fp = os_open(tmp_name, OS_OPEN_REQUIRE_NEW | OS_OPEN_WRITE);
        os_write(fp, DEBUGGER_COMMAND, strlen(DEBUGGER_COMMAND));
        os_close(fp);

        fd = open_syscall(tmp_name, O_RDONLY, 0);
        if (fd < 0) {
            SYSLOG_INTERNAL_ERROR("ERROR: open failed on temporary file");
            exit_process_syscall(1);
        }
#if !BATCH_MODE
        /* Redirect stdin from the temporary file */
        close_syscall(0); /* close stdin */
        dup_syscall(fd);  /* replace file descriptor 0 with reference to temp file */
#endif
        close_syscall(fd); /* close the other reference to temporary file */

        /* Find the core file */
        strncpy(core_name, CORE_NAME, 127);
        core_name[127] = '\0'; /* if max no null */
        fd = open_syscall(core_name, O_RDONLY, 0);
        if (fd < 0) {
            snprintf(core_name, 128, "%s.%d", CORE_NAME, core_pid);
            SYSLOG_INTERNAL_ERROR("core not found, trying %s", core_name);
            fd = open_syscall(core_name, O_RDONLY, 0);
            if (fd < 0) {
                SYSLOG_INTERNAL_ERROR("ERROR: no core file found!");
                exit_process_syscall(1);
            }
        }
        close_syscall(fd);

        /* avoid running the debugger under us!
         * FIXME: just remove our libraries, instead of entire env var?
         */
        unsetenv("LD_PRELOAD");

        SYSLOG_INTERNAL_ERROR("-------------------------------------------");
        SYSLOG_INTERNAL_ERROR("stackdump: --- now running the debugger ---");
        SYSLOG_INTERNAL_ERROR("%s %s %s %s", DEBUGGER, QUIET_MODE, exec_name, core_name);
        SYSLOG_INTERNAL_ERROR("-------------------------------------------");
        i = 0;
        /* We rely on /usr/bin/env to do the PATH search for gdb on our behalf.
         */
        argv[i++] = "/usr/bin/env";
        argv[i++] = DEBUGGER;
        argv[i++] = QUIET_MODE;
#if BATCH_MODE
        argv[i++] = "-x";
        argv[i++] = tmp_name;
        argv[i++] = "-batch";
#endif
        argv[i++] = exec_name;
        argv[i++] = core_name;
        argv[i++] = NULL;
        execve_errno = execve_syscall("/usr/bin/env", argv, our_environ);
        SYSLOG_INTERNAL_ERROR("ERROR: execve failed for debugger: %d", -execve_errno);
        exit_process_syscall(1);
    } else if (pid == -1) {
        SYSLOG_INTERNAL_ERROR("ERROR: could not fork to run debugger");
        exit_process_syscall(1);
    }
    /* Parent continues */
    /* while(wait(NULL)>0) waits for all children, and could hang, so: */
    while (wait_syscall(NULL) != pid) {
        /* empty loop */
    }

    /* Wait for these children to complete before returning */

    while (wait_syscall(NULL) > 0) {
        /* empty loop */
    }

    os_delete_file(tmp_name); /* clean up the temporary file */
    SYSLOG_INTERNAL_ERROR("-------------------------------------------");
}