Пример #1
0
void default_actor_addressing::write(serializer* sink, const actor_ptr& ptr) {
    CPPA_REQUIRE(sink != nullptr);
    if (ptr == nullptr) {
        CPPA_LOGMF(CPPA_DEBUG, self, "serialized nullptr");
        sink->begin_object("@0");
        sink->end_object();
    }
    else {
        // local actor?
        if (!ptr->is_proxy()) {
            get_actor_registry()->put(ptr->id(), ptr);
        }
        auto pinf = m_pinf;
        if (ptr->is_proxy()) {
            auto dptr = ptr.downcast<default_actor_proxy>();
            if (dptr) pinf = dptr->process_info();
            else CPPA_LOGMF(CPPA_ERROR, self, "downcast failed");
        }
        sink->begin_object("@actor");
        sink->write_value(ptr->id());
        sink->write_value(pinf->process_id());
        sink->write_raw(process_information::node_id_size,
                        pinf->node_id().data());
        sink->end_object();
    }
}
Пример #2
0
/*
 * We treat lstat the same as read except that only the existence or
 * nonexistence of the file is stored (represented as either the all
 * zero hash or the all one hash).
 */
int action_lstat(const char *path)
{
    // Not all programs access files in a correct acyclic order.
    // In particular, GNU as stats its output .o file before writing
    // it.  To fix this flaw, we lie to GNU as and pretend the file
    // is never there when statted.
    // TODO: This mechanism should be generalized and moved into a user
    // customizable file.
    struct process *process = process_info();
    if ((process->flags & HACK_SKIP_O_STAT) && endswith(path, ".o")) {
        wlog("skipping stat(\"%s\")", path);
        return 0;
    }

    process = lock_master_process();

    // Add a stat node to the subgraph
    struct hash path_hash;
    remember_hash_path(&path_hash, path);
    new_node(process, SG_STAT, &path_hash);

    // Check existence and update snapshot
    struct hash exists_hash;
    struct snapshot_entry *entry = snapshot_update(&exists_hash, path, &path_hash, 0);
    // No need to check for writers; if the file is being written, it must exist
    entry->stat = 1;
    shared_map_unlock(&snapshot);

    add_parent(process, &exists_hash);
    unlock_master_process();
    return !hash_is_null(&exists_hash);
}
Пример #3
0
 int main()
 {
         int sock_fd,conn_fd;
         int client_len;
         pid_t pid;
         struct sockaddr_in addr_serv,addr_client;
         sock_fd = socket(AF_INET,SOCK_STREAM,0);
         if(sock_fd < 0){
                 perror("socket");
                 exit(1);
         } else {
                 printf("sock sucessful\n");
         }
         //初始化服务器端地址
         memset(&addr_serv,0,sizeof(addr_serv));
         addr_serv.sin_family = AF_INET;
         addr_serv.sin_port = htons(SOURCE_PORT);
         addr_serv.sin_addr.s_addr =inet_addr(SOURCE_IP_ADDRESS);
         client_len = sizeof(struct sockaddr_in);
         if(bind(sock_fd,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr_in))<0){
                 perror("bind");
                 exit(1);
         } else {
                 printf("bind sucess\n");
         }
         if (listen(sock_fd,QUEUE_LINE) < 0){
                 perror("listen");
                 exit(1);
         } else {
                 printf("listen sucessful\n");
         }
       //  while(1){
                  printf("begin accept:\n");
                  conn_fd = accept(sock_fd,(struct sockaddr *)&addr_client,&client_len);

                  if(conn_fd < 0){
                         perror("accept");
                         exit(1);
                  }
                  printf("accept a new client,ip:%s\n",inet_ntoa(addr_client.sin_addr));
         /*         pid = fork();
                  if(0 == pid){         //子进程
                         close(sock_fd);//在子进程中关闭服务器的侦听
                         process_info(conn_fd);//处理信息
                  } else {
                         close(conn_fd);//在父进程中关闭客户端的连接
                  }*/
                 close(sock_fd);//在子进程中关闭服务器的侦听
                 process_info(conn_fd);//
               //  close(conn_fd);
        // }
 
 }
void LIR_OopMapGenerator::iterate_one(BlockBegin* block) {
#ifndef PRODUCT
  if (TraceLIROopMaps) {
    tty->print_cr("Iterating through block %d", block->block_id());
  }
#endif

  set_block(block);
  block->set(BlockBegin::lir_oop_map_gen_reachable_flag);

  int i;

  if (!is_caching_change_block(block)) {
    LIR_OpVisitState state;
    LIR_OpList* inst = block->lir()->instructions_list();
    int length = inst->length();
    for (i = 0; i < length; i++) {
      LIR_Op* op = inst->at(i);
      LIR_Code code = op->code();

      state.visit(op);
      for (int j = 0; j < state.info_count(); j++) {
        process_info(state.info_at(j));
      }

      if (code == lir_volatile_move ||
          code == lir_move) {
        process_move(op);
      }
    }
  }

  // Process successors
  if (block->end() != _base) {
    for (i = 0; i < block->end()->number_of_sux(); i++) {
      merge_state(block->end()->sux_at(i));
    }
  } else {
    // Do not traverse OSR entry point of the base
    merge_state(_base->std_entry());
  }

  set_block(NULL);
}
Пример #5
0
static int process_list(int size, SFInfo *sf, FILE *fd)
{
	SFChunk chunk;

	/* read the following id string */
	READID(chunk.id, fd); size -= 4;
	
	switch (chunkid(chunk.id)) {
	case INFO_ID:
		return process_info(size, sf, fd);
	case SDTA_ID:
		return process_sdta(size, sf, fd);
	case PDTA_ID:
		return process_pdta(size, sf, fd);
	default:
		fprintf(stderr, "*** illegal id in level 1: %4.4s\n", chunk.id);
		FSKIP(size, fd); /* skip it */
		return 0;
	}
}
Пример #6
0
int Instruments::process_list(int size, SFInfo *sf, struct timidity_file *fd)
{
	SFChunk chunk;

	/* read the following id string */
	READID(chunk.id, fd); size -= 4;
	ctl_cmsg(CMSG_INFO, VERB_DEBUG, "%c%c%c%c:",
		chunk.id[0], chunk.id[1], chunk.id[2], chunk.id[3]);
	switch (chunkid(chunk.id)) {
	case INFO_ID:
		return process_info(size, sf, fd);
	case SDTA_ID:
		return process_sdta(size, sf, fd);
	case PDTA_ID:
		return process_pdta(size, sf, fd);
	default:
		ctl_cmsg(CMSG_WARNING, VERB_NORMAL,	"%s: *** illegal id in level 1: %4.4s",	fd->filename.c_str(), chunk.id);
		FSKIP(size, fd); /* skip it */
		return 0;
	}
}
Пример #7
0
static inline void stat()
{
    SYSTIME uptime;
    int i;
    unsigned int diff;

    get_uptime(&uptime);
    for (i = 0; i < TEST_ROUNDS; ++i)
        svc_test();
    diff = systime_elapsed_us(&uptime);
    printf("average kernel call time: %d.%dus\n", diff / TEST_ROUNDS, (diff / (TEST_ROUNDS / 10)) % 10);

    get_uptime(&uptime);
    for (i = 0; i < TEST_ROUNDS; ++i)
        process_switch_test();
    diff = systime_elapsed_us(&uptime);
    printf("average switch time: %d.%dus\n", diff / TEST_ROUNDS, (diff / (TEST_ROUNDS / 10)) % 10);

    printf("core clock: %d\n", power_get_core_clock());
    process_info();
}
void default_actor_addressing::write(serializer* sink, const actor_ptr& ptr) {
    CPPA_REQUIRE(sink != nullptr);
    if (ptr == nullptr) {
        CPPA_LOG_DEBUG("serialize nullptr");
        sink->write_value(static_cast<actor_id>(0));
        process_information::serialize_invalid(sink);
    }
    else {
        // local actor?
        if (!ptr->is_proxy()) {
            get_actor_registry()->put(ptr->id(), ptr);
        }
        auto pinf = m_pinf;
        if (ptr->is_proxy()) {
            auto dptr = ptr.downcast<default_actor_proxy>();
            if (dptr) pinf = dptr->process_info();
            else CPPA_LOG_ERROR("downcast failed");
        }
        sink->write_value(ptr->id());
        sink->write_value(pinf->process_id());
        sink->write_raw(process_information::node_id_size,
                        pinf->node_id().data());
    }
}
Пример #9
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;
    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");
}
Пример #10
0
void
do_break(void)
{
    int i;
#ifdef __WIN32__
    char *mode; /* enough for storing "window" */

    /* check if we're in console mode and, if so,
       halt immediately if break is called */
    mode = erts_read_env("ERL_CONSOLE_MODE");
    if (mode && strcmp(mode, "window") != 0)
	erl_exit(0, "");
    erts_free_read_env(mode);
#endif /* __WIN32__ */

    erts_printf("\n"
		"BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded\n"
		"       (v)ersion (k)ill (D)b-tables (d)istribution\n");

    while (1) {
	if ((i = sys_get_key(0)) <= 0)
	    erl_exit(0, "");
	switch (i) {
	case 'q':
	case 'a': 
	case '*': /* 
		   * The asterisk is an read error on windows, 
		   * where sys_get_key isn't that great in console mode.
		   * The usual reason for a read error is Ctrl-C. Treat this as
		   * 'a' to avoid infinite loop.
		   */
	    erl_exit(0, "");
	case 'A':		/* Halt generating crash dump */
	    erl_exit(1, "Crash dump requested by user");
	case 'c':
	    return;
	case 'p':
	    process_info(ERTS_PRINT_STDOUT, NULL);
	    return;
	case 'm':
	    return;
	case 'o':
	    port_info(ERTS_PRINT_STDOUT, NULL);
	    return;
	case 'i':
	    info(ERTS_PRINT_STDOUT, NULL);
	    return;
	case 'l':
	    loaded(ERTS_PRINT_STDOUT, NULL);
	    return;
	case 'v':
	    erts_printf("Erlang (%s) emulator version "
		       ERLANG_VERSION "\n",
		       EMULATOR);
	    erts_printf("Compiled on " ERLANG_COMPILE_DATE "\n");
	    return;
	case 'd':
	    distribution_info(ERTS_PRINT_STDOUT, NULL);
	    return;
	case 'D':
	    db_info(ERTS_PRINT_STDOUT, NULL, 1);
	    return; 
	case 'k':
	    process_killer();
	    return;
#ifdef OPPROF
	case 'X':
	    dump_frequencies();
	    return;
	case 'x':
	    {
		int i;
		for (i = 0; i <= HIGHEST_OP; i++) {
		    if (opc[i].name != NULL) {
			erts_printf("%-16s %8d\n", opc[i].name, opc[i].count);
		    }
		}
	    }
	    return;
	case 'z':
	    {
		int i;
		for (i = 0; i <= HIGHEST_OP; i++)
		    opc[i].count = 0;
	    }
	    return;
#endif
#ifdef DEBUG
	case 't':
	    erts_p_slpq();
	    return;
	case 'b':
	    bin_check();
	    return;
	case 'C':
	    abort();
#endif
	case '\n':
	    continue;
	default:
	    erts_printf("Eh?\n\n");
	}
    }

}
Пример #11
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);
}
Пример #12
0
/*
 * action_execve adds an exec node to the subgraph and sets WAITLESS_PARENT
 * to the hash of the arguments.  The first node in the child process will
 * use WAITLESS_PARENT as its first parent node.  Note that WAITLESS_PARENT
 * is intentionally _not_ the same as the exec node; this encodes the idea
 * that child processes depend on their parent processes only through the
 * arguments to execve (and the current directory).
 *
 * In the case of shared spines (due to pipes or other IPC mechanisms) the
 * exec node encodes only the path without argv and envp and WAITLESS_PARENT
 * has the format #id where id is a SYSV shared memory id.  This allows further
 * subgraph nodes from child and parent to be interleaved.  Since in the shared
 * case the child _does_ descend directly from the exec node, an explicit
 * record of argv and envp would be redundant.
 */
int action_execve(const char *path, const char *const argv[], const char *const envp[])
{
    fd_map_dump();
    struct process *process = lock_master_process();
    int linked = process != process_info();
    wlog("exec: linked %d", linked);

    // Pack all the arguments into a single buffer.  The format is
    //     char path[];
    //     uint32_t argc;
    //     char argv[argc][];
    //     char is_pipe;
    //     uint32_t envc;
    //     char envp[envc][];
    //     char cwd[];
    // with all strings packed together with terminating nulls.
    char data[4096];
    char *p = data;
#define ADD_STR(s) p += strlcpy(p, (s), data+sizeof(data)-p) + 1
    ADD_STR(path);
    // encode argv
    char *cp = p;
    p += sizeof(uint32_t); // skip 4 bytes for len(argv)
    uint32_t i;
    for (i = 0; argv[i]; i++)
        ADD_STR(argv[i]);
    memcpy(cp, &i, sizeof(uint32_t));
    *p++ = linked;
    // encode envp
    cp = p;
    p += sizeof(uint32_t); // skip 4 bytes for len(envp)
    uint32_t count;
    for (i = 0; envp[i]; i++)
        if (!startswith(envp[i], "WAITLESS")) {
            ADD_STR(envp[i]);
            count++;
        }
    memcpy(cp, &count, sizeof(uint32_t));
    // encode pwd
    if (!real_getcwd(p, data+sizeof(data)-p))
        die("action_execve: getcwd failed: %s", strerror(errno));
    int n = p - data + strlen(p) + 1;
#undef ADD_STR

    // Store exec data and create a corresponding exec node
    struct hash data_hash;
    remember_hash_memory(&data_hash, data, n);
    new_node(process, SG_EXEC, &data_hash);

    // Add the program to the snapshot
    struct hash path_hash, program_hash;
    remember_hash_path(&path_hash, path);
    struct snapshot_entry *entry = snapshot_update(&program_hash, path, &path_hash, 1);
    if (entry->writing)
        die("can't exec '%s' while it is being written", path); // TODO: block instead of dying
    entry->read = 1;
    shared_map_unlock(&snapshot);

    // TODO: Run ldd/otool and hash all shared library dependencies as well
    // TODO: Complain if the program is statically linked
    // TODO: If we decide it's worth it, parse #! lines and hash interpreters
    // too.  That seems easy enough to probably be worth it.

    // If not linked, set parents to the new child values
    if (!linked) {
        process->parents.n = 2; 
        process->parents.p[0] = data_hash;
        process->parents.p[1] = program_hash;
    }

    unlock_master_process();

    // Update process flags
    process = lock_process();
    int old_flags = process->flags;
    process->flags = 0;
    p = rindex(path, '/');
    const char *name = p ? p+1 : path;
    if (!strcmp(name, "as"))
        process->flags |= HACK_SKIP_O_STAT;
    else if (strstr(name, "-gcc-")) {
        for (i = 1; argv[i]; i++)
            if (!strcmp(argv[i], "-c")) {
                process->flags |= HACK_SKIP_O_STAT;
                break;
            }
    }
    unlock_process();

    // Do the exec
    int ret = real_execve(path, argv, envp);

    // An error must have occurred; reset flags back to old value
    process = lock_process();
    process->flags = old_flags;
    unlock_process();
    return ret;
}
Пример #13
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;
    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);
}