static int dump_node(pNode node) { switch(node->type) { case literal: printf("\"%s\"", node->data); break; case symbol: printf("{%s", node->data); if(node->params) { printf("("); dump_atoms(node->params); printf(")"); }; printf("}"); break; case mapping: dump_node(node->params); printf(" > %s", node->data); break; case deref: printf("DEREF("); dump_node(node->params); printf(")"); break; case var_conddef: printf("%s << ", node->data); dump_node(node->params); break; case var_def: printf("%s = ", node->data); dump_node(node->params); break; case code: printf("code:"); dump_code(node->data); break; break; }; };
/* 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"); }
int main(int argc, char *argv[]) { unsigned abits = DATA_BTREE_BIT|CTIME_SIZE_BIT|MODE_OWNER_BIT|LINK_COUNT_BIT|MTIME_BIT; struct dev *dev = &(struct dev){ .bits = 8, .fd = open(argv[1], O_CREAT|O_RDWR, S_IRUSR|S_IWUSR) }; assert(!ftruncate(dev->fd, 1 << 24)); init_buffers(dev, 1 << 20, 0); struct sb *sb = rapid_sb(dev, .version = 0, .atomref_base = 1 << 10, .unatom_base = 1 << 11, .atomgen = 1); struct inode *inode = rapid_open_inode(sb, NULL, S_IFDIR | 0x666, .present = abits, .i_uid = 0x12121212, .i_gid = 0x34343434, .i_ctime = spectime(0xdec0debeadULL), .i_mtime = spectime(0xbadfaced00dULL)); inode->btree = (struct btree){ .root = { .block = 0xcaba1f00dULL, .depth = 3 } }; sb->atable = inode; for (int i = 0; i < 2; i++) { struct buffer_head *buffer = blockget(mapping(inode), tux_sb(inode->i_sb)->atomref_base + i); memset(bufdata(buffer), 0, sb->blocksize); blockput_dirty(buffer); } if (1) { warn("---- test positive and negative refcount carry ----"); use_atom(inode, 6, 1 << 15); use_atom(inode, 6, (1 << 15)); use_atom(inode, 6, -(1 << 15)); use_atom(inode, 6, -(1 << 15)); } warn("---- test atom table ----"); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "bar", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "foo", 3)); printf("atom = %Lx\n", (L)make_atom(inode, "bar", 3)); warn("---- test inode xattr cache ----"); int err; err = xcache_update(inode, 0x666, "hello", 5, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x777, "world!", 6, 0); if (err) printf("err %d\n", err); xcache_dump(inode); struct xattr *xattr = xcache_lookup(tux_inode(inode)->xcache, 0x777); if (!IS_ERR(xattr)) printf("atom %x => %.*s\n", xattr->atom, xattr->size, xattr->body); err = xcache_update(inode, 0x111, "class", 5, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x666, NULL, 0, 0); if (err) printf("err %d\n", err); err = xcache_update(inode, 0x222, "boooyah", 7, 0); if (err) printf("err %d\n", err); xcache_dump(inode); warn("---- test xattr inode table encode and decode ----"); char attrs[1000] = { }; char *top = encode_xattrs(inode, attrs, sizeof(attrs)); hexdump(attrs, top - attrs); printf("predicted size = %x, encoded size = %Lx\n", encode_xsize(inode), (L)(top - attrs)); inode->xcache->size = offsetof(struct xcache, xattrs); char *newtop = decode_attrs(inode, attrs, top - attrs); printf("predicted size = %x, xcache size = %x\n", decode_xsize(inode, attrs, top - attrs), inode->xcache->size); assert(top == newtop); xcache_dump(inode); free(inode->xcache); inode->xcache = NULL; warn("---- xattr update ----"); set_xattr(inode, "hello", 5, "world!", 6, 0); set_xattr(inode, "empty", 5, "zot", 0, 0); set_xattr(inode, "foo", 3, "foobar", 6, 0); xcache_dump(inode); warn("---- xattr remove ----"); // del_xattr(inode, "hello", 5); xcache_dump(inode); warn("---- xattr lookup ----"); for (int i = 0, len; i < 3; i++) { char *namelist[] = { "hello", "foo", "world" }, *name = namelist[i]; char data[100]; int size = get_xattr(inode, name, len = strlen(name), data, sizeof(data)); if (size < 0) printf("xattr %.*s not found (%s)\n", len, name, strerror(-size)); else printf("found xattr %.*s => %.*s\n", len, name, size, data); } warn("---- list xattrs ----"); int len = xattr_list(inode, attrs, sizeof(attrs)); printf("xattr list length = %i\n", xattr_list(inode, NULL, 0)); hexdump(attrs, len); warn("---- atom reverse map ----"); for (int i = 0; i < 5; i++) { unsigned atom = i, offset; struct buffer_head *buffer = blockread_unatom(inode, atom, &offset); loff_t where = from_be_u64(((be_u64 *)bufdata(buffer))[offset]); blockput_dirty(buffer); buffer = blockread(mapping(inode), where >> sb->blockbits); printf("atom %.3Lx at dirent %.4Lx, ", (L)atom, (L)where); hexdump(bufdata(buffer) + (where & sb->blockmask), 16); blockput(buffer); } warn("---- atom recycle ----"); set_xattr(inode, "hello", 5, NULL, 0, 0); show_freeatoms(sb); printf("got free atom %x\n", get_freeatom(inode)); printf("got free atom %x\n", get_freeatom(inode)); printf("got free atom %x\n", get_freeatom(inode)); warn("---- dump atom table ----"); dump_atoms(inode); show_buffers(inode->map); exit(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); }
static int option_iter(pOption opt, int param) { printf("\t\t"); dump_atoms(opt->atoms); printf("\n"); };
/* 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; time_t now; size_t dumpnamebufsize = MAXPATHLEN; char dumpnamebuf[MAXPATHLEN]; char* dumpname; 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 erts_sys_prepare_crash_dump(); if (erts_sys_getenv_raw("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.1\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_proc.tab) 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); }