Exemplo n.º 1
0
Arquivo: break.c Projeto: easemob/otp
/* XXX THIS SHOULD BE IN SYSTEM !!!! */
void
erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
{
#ifdef ERTS_SMP
    ErtsThrPrgrData tpd_buf; /* in case we aren't a managed thread... */
#endif
    int fd;
    size_t envsz;
    time_t now;
    char env[21]; /* enough to hold any 64-bit integer */
    size_t dumpnamebufsize = MAXPATHLEN;
    char dumpnamebuf[MAXPATHLEN];
    char* dumpname;
    int secs;
    int env_erl_crash_dump_seconds_set = 1;
    int i;

    if (ERTS_SOMEONE_IS_CRASH_DUMPING)
	return;

#ifdef ERTS_SMP
    /* Order all managed threads to block, this has to be done
       first to guarantee that this is the only thread to generate
       crash dump. */
    erts_thr_progress_fatal_error_block(&tpd_buf);

#ifdef ERTS_THR_HAVE_SIG_FUNCS
    /*
     * We suspend all scheduler threads so that we can dump some
     * data about the currently running processes and scheduler data.
     * We have to be very very careful when doing this as the schedulers
     * could be anywhere.
     */
    for (i = 0; i < erts_no_schedulers; i++) {
        erts_tid_t tid = ERTS_SCHEDULER_IX(i)->tid;
        if (!erts_equal_tids(tid,erts_thr_self()))
            sys_thr_suspend(tid);
    }

#endif

    /* Allow us to pass certain places without locking... */
    erts_smp_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
    erts_smp_tsd_set(erts_is_crash_dumping_key, (void *) 1);

#else /* !ERTS_SMP */
    erts_writing_erl_crash_dump = 1;
#endif /* ERTS_SMP */

    envsz = sizeof(env);
    /* ERL_CRASH_DUMP_SECONDS not set
     * if we have a heart port, break immediately
     * otherwise dump crash indefinitely (until crash is complete)
     * same as ERL_CRASH_DUMP_SECONDS = 0
     * - do not write dump
     * - do not set an alarm
     * - break immediately
     *
     * ERL_CRASH_DUMP_SECONDS = 0
     * - do not write dump
     * - do not set an alarm
     * - break immediately
     *
     * ERL_CRASH_DUMP_SECONDS < 0
     * - do not set alarm
     * - write dump until done
     *
     * ERL_CRASH_DUMP_SECONDS = S (and S positive)
     * - Don't dump file forever
     * - set alarm (set in sys)
     * - write dump until alarm or file is written completely
     */
	
    if (erts_sys_getenv__("ERL_CRASH_DUMP_SECONDS", env, &envsz) != 0) {
	env_erl_crash_dump_seconds_set = 0;
	secs = -1;
    } else {
	env_erl_crash_dump_seconds_set = 1;
	secs = atoi(env);
    }

    if (secs == 0) {
	return;
    }

    /* erts_sys_prepare_crash_dump returns 1 if heart port is found, otherwise 0
     * If we don't find heart (0) and we don't have ERL_CRASH_DUMP_SECONDS set
     * we should continue writing a dump
     *
     * beware: secs -1 means no alarm
     */

    if (erts_sys_prepare_crash_dump(secs) && !env_erl_crash_dump_seconds_set ) {
	return;
    }

    if (erts_sys_getenv__("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
	dumpname = "erl_crash.dump";
    else
	dumpname = &dumpnamebuf[0];
    
    erts_fprintf(stderr,"\nCrash dump is being written to: %s...", dumpname);

    fd = open(dumpname,O_WRONLY | O_CREAT | O_TRUNC,0640);
    if (fd < 0)
	return; /* Can't create the crash dump, skip it */
    time(&now);
    erts_fdprintf(fd, "=erl_crash_dump:0.3\n%s", ctime(&now));

    if (file != NULL)
       erts_fdprintf(fd, "The error occurred in file %s, line %d\n", file, line);

    if (fmt != NULL && *fmt != '\0') {
	erts_fdprintf(fd, "Slogan: ");
	erts_vfdprintf(fd, fmt, args);
    }
    erts_fdprintf(fd, "System version: ");
    erts_print_system_version(fd, NULL, NULL);
    erts_fdprintf(fd, "%s\n", "Compiled: " ERLANG_COMPILE_DATE);

    erts_fdprintf(fd, "Taints: ");
    erts_print_nif_taints(fd, NULL);
    erts_fdprintf(fd, "Atoms: %d\n", atom_table_size());

#ifdef USE_THREADS
    /* We want to note which thread it was that called erl_exit */
    if (erts_get_scheduler_data()) {
        erts_fdprintf(fd, "Calling Thread: scheduler:%d\n",
                      erts_get_scheduler_data()->no);
    } else {
        if (!erts_thr_getname(erts_thr_self(), dumpnamebuf, MAXPATHLEN))
            erts_fdprintf(fd, "Calling Thread: %s\n", dumpnamebuf);
        else
            erts_fdprintf(fd, "Calling Thread: %p\n", erts_thr_self());
    }
#else
    erts_fdprintf(fd, "Calling Thread: scheduler:1\n");
#endif

#if defined(ERTS_HAVE_TRY_CATCH)

    /*
     * erts_print_scheduler_info is not guaranteed to be safe to call
     * here for all schedulers as we may have suspended a scheduler
     * in the middle of updating the STACK_TOP and STACK_START
     * variables and thus when scanning the stack we could get
     * segmentation faults. We protect against this very unlikely
     * scenario by using the ERTS_SYS_TRY_CATCH.
     */
    for (i = 0; i < erts_no_schedulers; i++) {
        ERTS_SYS_TRY_CATCH(
            erts_print_scheduler_info(fd, NULL, ERTS_SCHEDULER_IX(i)),
            erts_fdprintf(fd, "** crashed **\n"));
    }
#endif

#ifdef ERTS_SMP

#if defined(ERTS_THR_HAVE_SIG_FUNCS)

    /* We resume all schedulers so that we are in a known safe state
       when we write the rest of the crash dump */
    for (i = 0; i < erts_no_schedulers; i++) {
        erts_tid_t tid = ERTS_SCHEDULER_IX(i)->tid;
        if (!erts_equal_tids(tid,erts_thr_self()))
	    sys_thr_resume(tid);
    }
#endif

    /*
     * Wait for all managed threads to block. If all threads haven't blocked
     * after a minute, we go anyway and hope for the best...
     *
     * We do not release system again. We expect an exit() or abort() after
     * dump has been written.
     */
    erts_thr_progress_fatal_error_wait(60000);
    /* Either worked or not... */
#endif

#ifndef ERTS_HAVE_TRY_CATCH
    /* This is safe to call here, as all schedulers are blocked */
    for (i = 0; i < erts_no_schedulers; i++) {
        erts_print_scheduler_info(fd, NULL, ERTS_SCHEDULER_IX(i));
    }
#endif
    
    info(fd, NULL); /* General system info */
    if (erts_ptab_initialized(&erts_proc))
	process_info(fd, NULL); /* Info about each process and port */
    db_info(fd, NULL, 0);
    erts_print_bif_timer_info(fd, NULL);
    distribution_info(fd, NULL);
    erts_fdprintf(fd, "=loaded_modules\n");
    loaded(fd, NULL);
    erts_dump_fun_entries(fd, NULL);
    erts_deep_process_dump(fd, NULL);
    erts_fdprintf(fd, "=atoms\n");
    dump_atoms(fd, NULL);

    /* Keep the instrumentation data at the end of the dump */
    if (erts_instr_memory_map || erts_instr_stat) {
	erts_fdprintf(fd, "=instr_data\n");

	if (erts_instr_stat) {
	    erts_fdprintf(fd, "=memory_status\n");
	    erts_instr_dump_stat_to_fd(fd, 0);
	}
	if (erts_instr_memory_map) {
	    erts_fdprintf(fd, "=memory_map\n");
	    erts_instr_dump_memory_map_to_fd(fd);
	}
    }

    erts_fdprintf(fd, "=end\n");
    close(fd);
    erts_fprintf(stderr,"done\n");
}
Exemplo n.º 2
0
/* XXX THIS SHOULD BE IN SYSTEM !!!! */
void
erl_crash_dump_v(char *file, int line, char* fmt, va_list args)
{
#ifdef ERTS_SMP
    ErtsThrPrgrData tpd_buf; /* in case we aren't a managed thread... */
#endif
    int fd;
    size_t envsz;
    time_t now;
    char env[21]; /* enough to hold any 64-bit integer */
    size_t dumpnamebufsize = MAXPATHLEN;
    char dumpnamebuf[MAXPATHLEN];
    char* dumpname;
    int secs;
    int env_erl_crash_dump_seconds_set = 1;

    if (ERTS_SOMEONE_IS_CRASH_DUMPING)
	return;

#ifdef ERTS_SMP
    /*
     * Wait for all managed threads to block. If all threads haven't blocked
     * after a minute, we go anyway and hope for the best...
     *
     * We do not release system again. We expect an exit() or abort() after
     * dump has been written.
     */
    erts_thr_progress_fatal_error_block(60000, &tpd_buf);
    /* Either worked or not... */

    /* Allow us to pass certain places without locking... */
    erts_smp_atomic32_set_mb(&erts_writing_erl_crash_dump, 1);
    erts_smp_tsd_set(erts_is_crash_dumping_key, (void *) 1);
#else
    erts_writing_erl_crash_dump = 1;
#endif

    envsz = sizeof(env);
    /* ERL_CRASH_DUMP_SECONDS not set
     * if we have a heart port, break immediately
     * otherwise dump crash indefinitely (until crash is complete)
     * same as ERL_CRASH_DUMP_SECONDS = 0
     * - do not write dump
     * - do not set an alarm
     * - break immediately
     *
     * ERL_CRASH_DUMP_SECONDS = 0
     * - do not write dump
     * - do not set an alarm
     * - break immediately
     *
     * ERL_CRASH_DUMP_SECONDS < 0
     * - do not set alarm
     * - write dump until done
     *
     * ERL_CRASH_DUMP_SECONDS = S (and S positive)
     * - Don't dump file forever
     * - set alarm (set in sys)
     * - write dump until alarm or file is written completely
     */
	
    if (erts_sys_getenv__("ERL_CRASH_DUMP_SECONDS", env, &envsz) != 0) {
	env_erl_crash_dump_seconds_set = 0;
	secs = -1;
    } else {
	env_erl_crash_dump_seconds_set = 1;
	secs = atoi(env);
    }

    if (secs == 0) {
	return;
    }

    /* erts_sys_prepare_crash_dump returns 1 if heart port is found, otherwise 0
     * If we don't find heart (0) and we don't have ERL_CRASH_DUMP_SECONDS set
     * we should continue writing a dump
     *
     * beware: secs -1 means no alarm
     */

    if (erts_sys_prepare_crash_dump(secs) && !env_erl_crash_dump_seconds_set ) {
	return;
    }

    if (erts_sys_getenv__("ERL_CRASH_DUMP",&dumpnamebuf[0],&dumpnamebufsize) != 0)
	dumpname = "erl_crash.dump";
    else
	dumpname = &dumpnamebuf[0];

    fd = open(dumpname,O_WRONLY | O_CREAT | O_TRUNC,0640);
    if (fd < 0) 
	return; /* Can't create the crash dump, skip it */
    
    time(&now);
    erts_fdprintf(fd, "=erl_crash_dump:0.3\n%s", ctime(&now));

    if (file != NULL)
       erts_fdprintf(fd, "The error occurred in file %s, line %d\n", file, line);

    if (fmt != NULL && *fmt != '\0') {
	erts_fdprintf(fd, "Slogan: ");
	erts_vfdprintf(fd, fmt, args);
    }
    erts_fdprintf(fd, "System version: ");
    erts_print_system_version(fd, NULL, NULL);
    erts_fdprintf(fd, "%s\n", "Compiled: " ERLANG_COMPILE_DATE);
    erts_fdprintf(fd, "Taints: ");
    erts_print_nif_taints(fd, NULL);
    erts_fdprintf(fd, "Atoms: %d\n", atom_table_size());
    info(fd, NULL); /* General system info */
    if (erts_ptab_initialized(&erts_proc))
	process_info(fd, NULL); /* Info about each process and port */
    db_info(fd, NULL, 0);
    erts_print_bif_timer_info(fd, NULL);
    distribution_info(fd, NULL);
    erts_fdprintf(fd, "=loaded_modules\n");
    loaded(fd, NULL);
    erts_dump_fun_entries(fd, NULL);
    erts_deep_process_dump(fd, NULL);
    erts_fdprintf(fd, "=atoms\n");
    dump_atoms(fd, NULL);

    /* Keep the instrumentation data at the end of the dump */
    if (erts_instr_memory_map || erts_instr_stat) {
	erts_fdprintf(fd, "=instr_data\n");

	if (erts_instr_stat) {
	    erts_fdprintf(fd, "=memory_status\n");
	    erts_instr_dump_stat_to_fd(fd, 0);
	}
	if (erts_instr_memory_map) {
	    erts_fdprintf(fd, "=memory_map\n");
	    erts_instr_dump_memory_map_to_fd(fd);
	}
    }

    erts_fdprintf(fd, "=end\n");
    close(fd);
    erts_fprintf(stderr,"\nCrash dump was written to: %s\n", dumpname);
}