예제 #1
0
/* 
 * Open a shared object
 */
int erts_sys_ddll_open(char *full_name, void **handle)
{
    MODULE_ID mid;
    int len;
    int ret = ERL_DE_NO_ERROR;
    static char dlname[PATH_MAX + EXT_LEN + 1];

    if ((mid = get_mid(full_name)) == NULL) {
	if ((len = sys_strlen(full_name)) > PATH_MAX-EXT_LEN-1) {
	    ret = ERL_DE_LOAD_ERROR_NAME_TO_LONG;
	    goto done;
	}
	sys_strcpy(dlname, full_name);
	sys_strcpy(dlname+len, FILE_EXT);
	if((mid = get_mid(dlname)) == NULL) {
	    sys_strcpy(dlname+len, ALT_FILE_EXT);
	    if((mid = get_mid(dlname)) == NULL) {
		ret = ERL_DE_DYNAMIC_ERROR_OFFSET - ((int) ModuleNotFound);
		goto done;
	    }
	}
    }
    *handle = (void *) mid;
 done:
    return ret;
}
예제 #2
0
/* 
 * Open a shared object
 */
int erts_sys_ddll_open2(const char *full_name, void **handle, ErtsSysDdllError* err)
{
    int len;
    char dlname[MAXPATHLEN + 1];
    
    if ((len = sys_strlen(full_name)) >= MAXPATHLEN - EXT_LEN) {
	if (err != NULL) {
	    err->str = "Library name too long";
	}
	return ERL_DE_LOAD_ERROR_NAME_TO_LONG;
    }
    sys_strcpy(dlname, full_name);
    sys_strcpy(dlname+len, FILE_EXT);
    return erts_sys_ddll_open_noext(dlname, handle, err);
}
예제 #3
0
static int __config_init( void )
{
    OSH_ERROR status = OSH_ERR_NONE;
    char temp_buf[1024];
    static int global_test_rc = 0;

    sys_memset(&osh_config, 0, sizeof(osh_config));

    osh_config.active = 0;
    if (gethostname(osh_config.hostname, sizeof(osh_config.hostname)) != 0)
    {
        sys_strcpy(osh_config.hostname, "localhost");
    }
    osh_config.my_pe = INVALID_PE;
    osh_config.num_pe = INVALID_PE;
    osh_config.rc = &global_test_rc; /*NULL*/
    /* 
     * Seed the random-number generator with current time so that
     * the numbers will be different every time we run.
     */
    osh_config.timer = (unsigned int)time( NULL );
    srand( osh_config.timer );

    PE_LIST_SET(DEFAULT_PE, osh_config.exec_mode.log_pe_list);
    osh_config.exec_mode.out_level = LOG_INFO;
    osh_config.exec_mode.out_file = stdout;

    osh_config.exec_mode.log_level = LOG_NONE;
    osh_config.exec_mode.log_file = NULL;
    sys_snprintf_safe(temp_buf, sizeof(temp_buf), "%s_%s_%04d.log", MODULE_NAME, osh_config.hostname, getpid());
    osh_config.exec_mode.log_file_name = sys_strdup(temp_buf);

    return status;
}
예제 #4
0
ErlDrvMutex *
erl_drv_mutex_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvMutex *dmtx = erts_alloc_fnf(ERTS_ALC_T_DRV_MTX,
				       (sizeof(ErlDrvMutex)
					+ (name ? sys_strlen(name) + 1 : 0)));
    if (dmtx) {
	ethr_mutex_opt opt = ETHR_MUTEX_OPT_DEFAULT_INITER;
	opt.posix_compliant = 1;
	if (ethr_mutex_init_opt(&dmtx->mtx, &opt) != 0) {
	    erts_free(ERTS_ALC_T_DRV_MTX, (void *) dmtx);
	    dmtx = NULL;
	}
	else if (!name)
	    dmtx->name = no_name;
	else {
	    dmtx->name = ((char *) dmtx) + sizeof(ErlDrvMutex);
	    sys_strcpy(dmtx->name, name);
	}
    }
    return dmtx;
#else
    return (ErlDrvMutex *) NULL;
#endif
}
예제 #5
0
ErlDrvCond *
erl_drv_cond_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvCond *dcnd = erts_alloc_fnf(ERTS_ALC_T_DRV_CND,
				      (sizeof(ErlDrvCond)
				       + (name ? sys_strlen(name) + 1 : 0)));
    if (dcnd) {
	ethr_cond_opt opt = ETHR_COND_OPT_DEFAULT_INITER;
	opt.posix_compliant = 1;
	if (ethr_cond_init_opt(&dcnd->cnd, &opt) != 0) {
	    erts_free(ERTS_ALC_T_DRV_CND, (void *) dcnd);
	    dcnd = NULL;
	}
	else if (!name)
	    dcnd->name = no_name;
	else {
	    dcnd->name = ((char *) dcnd) + sizeof(ErlDrvCond);
	    sys_strcpy(dcnd->name, name);
	}
    }
    return dcnd;
#else
    return (ErlDrvCond *) NULL;
#endif
}
예제 #6
0
int
erl_drv_thread_create(char *name,
		      ErlDrvTid *tid,
		      void* (*func)(void*),
		      void* arg,
		      ErlDrvThreadOpts *opts)
{
#ifdef USE_THREADS
    int res;
    struct ErlDrvTid_ *dtid;
    ethr_thr_opts ethr_opts;
    ethr_thr_opts *use_opts;

    if (!opts)
	use_opts = NULL;
    else {
	sys_memcpy((void *) &ethr_opts,
		   (void *) &def_ethr_opts,
		   sizeof(ethr_thr_opts));
	ethr_opts.suggested_stack_size = opts->suggested_stack_size;
	use_opts = &ethr_opts;
    }

    dtid = erts_alloc_fnf(ERTS_ALC_T_DRV_TID,
			  (sizeof(struct ErlDrvTid_)
			   + (name ? sys_strlen(name) + 1 : 0)));
    if (!dtid)
	return ENOMEM;

    dtid->drv_thr = 1;
    dtid->func = func;
    dtid->arg = arg;
    dtid->tsd = NULL;
    dtid->tsd_len = 0;
    if (!name)
	dtid->name = no_name;
    else {
	dtid->name = ((char *) dtid) + sizeof(struct ErlDrvTid_);
	sys_strcpy(dtid->name, name);
    }
#ifdef ERTS_ENABLE_LOCK_COUNT
    res = erts_lcnt_thr_create(&dtid->tid, erl_drv_thread_wrapper, dtid, use_opts);
#else
    res = ethr_thr_create(&dtid->tid, erl_drv_thread_wrapper, dtid, use_opts);
#endif

    if (res != 0) {
	erts_free(ERTS_ALC_T_DRV_TID, dtid);
	return res;
    }

    *tid = (ErlDrvTid) dtid;
    return 0;
#else
    return ENOTSUP;
#endif
}
예제 #7
0
Eterm
erts_lc_dump_graph(void)
{
    const char* basename = "lc_graph.";
    char filename[40];
    lc_matrix_t* tot = &tot_lc_matrix;
    lc_thread_t* thr;
    int i, j, name_max = 0;
    FILE* ff;

    lc_lock_threads();
    for (thr = lc_threads; thr; thr = thr->next) {
        collect_matrix(&thr->matrix);
    }
    lc_unlock_threads();

    sys_strcpy(filename, basename);
    sys_get_pid(filename + strlen(basename),
                sizeof(filename) - strlen(basename));
    ff = fopen(filename, "w");
    if (!ff)
        return am_error;

    for (i = 1; i < ERTS_LOCK_ORDER_SIZE; i++) {
        int len = strlen(erts_lock_order[i].name);
        if (name_max < len)
            name_max = len;
    }
    fputs("%This file was generated by erts_debug:lc_graph()\n\n", ff);
    fputs("%{ThisLockName, ThisLockId, LockedDirectlyBeforeThis, LockedIndirectlyBeforeThis}\n", ff);
    fprintf(ff, "[{%*s, %2d}", name_max, "\"NO LOCK\"", 0);
    for (i = 1; i < ERTS_LOCK_ORDER_SIZE; i++) {
        char* delim = "";
        fprintf(ff, ",\n {%*s, %2d, [", name_max, erts_lock_order[i].name, i);
        for (j = 0; j < ERTS_LOCK_ORDER_SIZE; j++) {
            if (tot->m[i][j] & 1) {
                fprintf(ff, "%s%d", delim, j);
                delim = ",";
            }
        }
        fprintf(ff, "], [");
        delim = "";
        for (j = 0; j < ERTS_LOCK_ORDER_SIZE; j++) {
            if (tot->m[i][j] == 2) {
                fprintf(ff, "%s%d", delim, j);
                delim = ",";
            }
        }
        fputs("]}", ff);
    }
    fputs("].", ff);
    fclose(ff);
    erts_fprintf(stderr, "Created file '%s' in current working directory\n",
                 filename);
    return am_ok;
}
예제 #8
0
/* 
 * Open a shared object
 */
int erts_sys_ddll_open2(char *full_name, void **handle, ErtsSysDdllError* err)
{
#if defined(HAVE_DLOPEN)
    char* dlname; 
    int len = sys_strlen(full_name);
    int ret;
    
    dlname = erts_alloc(ERTS_ALC_T_TMP, len + EXT_LEN + 1);
    sys_strcpy(dlname, full_name);
    sys_strcpy(dlname+len, FILE_EXT);
    
    ret = erts_sys_ddll_open_noext(dlname, handle, err);

    erts_free(ERTS_ALC_T_TMP, (void *) dlname);
    return ret;
#else
    return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;
#endif
}
예제 #9
0
/* 
 * Open a shared object
 */
int erts_sys_ddll_open2(char *full_name, void **handle, ErtsSysDdllError* err)
{
    int len;
    
    if (erts_sys_ddll_open_noext(full_name, handle, err) == ERL_DE_NO_ERROR) {
	return ERL_DE_NO_ERROR;
    }
    if ((len = sys_strlen(full_name)) > PATH_MAX-EXT_LEN) {
	return ERL_DE_LOAD_ERROR_NAME_TO_LONG;
    } else {
	static char dlname[PATH_MAX + 1];
	
	sys_strcpy(dlname, full_name);
	sys_strcpy(dlname+len, FILE_EXT);
	if (erts_sys_ddll_open_noext(dlname, handle, err) == ERL_DE_NO_ERROR) {
	    return ERL_DE_NO_ERROR;
	}
	sys_strcpy(dlname+len, ALT_FILE_EXT);
	return erts_sys_ddll_open_noext(dlname, handle, err);
    }
}
예제 #10
0
int erts_sys_ddll_sym2(void *handle, char *func_name, void **function, ErtsSysDdllError* err)
{
    FUNCPTR proc;
    static char statbuf[PREALLOC_BUFFER_SIZE];
    char *buf = statbuf;
    int need;

    if ((proc = lookup(func_name)) == NULL) {
	if ((need = strlen(func_name)+2) > PREALLOC_BUFFER_SIZE) {
	    buf = erts_alloc(ERTS_ALC_T_DDLL_TMP_BUF,need);
	}
	buf[0] = '_';
	sys_strcpy(buf+1,func_name);
	proc = lookup(buf);
	if (buf != statbuf) {
	    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, buf);
	}
	if (proc == NULL) {
	    return  ERL_DE_LOOKUP_ERROR_NOT_FOUND;
	}
    }
    *function = (void *) proc;
    return ERL_DE_NO_ERROR;
}
예제 #11
0
ErlDrvRWLock *
erl_drv_rwlock_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvRWLock *drwlck = erts_alloc_fnf(ERTS_ALC_T_DRV_RWLCK,
					  (sizeof(ErlDrvRWLock)
					   + (name ? sys_strlen(name) + 1 : 0)));
    if (drwlck) {
	if (ethr_rwmutex_init(&drwlck->rwmtx) != 0) {
	    erts_free(ERTS_ALC_T_DRV_RWLCK, (void *) drwlck);
	    drwlck = NULL;
	}
	else if (!name)
	    drwlck->name = no_name;
	else {
	    drwlck->name = ((char *) drwlck) + sizeof(ErlDrvRWLock);
	    sys_strcpy(drwlck->name, name);
	}
    }
    return drwlck;
#else
    return (ErlDrvRWLock *) NULL;
#endif
}
예제 #12
0
ErlDrvCond *
erl_drv_cond_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvCond *dcnd = erts_alloc_fnf(ERTS_ALC_T_DRV_CND,
				      (sizeof(ErlDrvCond)
				       + (name ? sys_strlen(name) + 1 : 0)));
    if (dcnd) {
	if (ethr_cond_init(&dcnd->cnd) != 0) {
	    erts_free(ERTS_ALC_T_DRV_CND, (void *) dcnd);
	    dcnd = NULL;
	}
	else if (!name)
	    dcnd->name = no_name;
	else {
	    dcnd->name = ((char *) dcnd) + sizeof(ErlDrvCond);
	    sys_strcpy(dcnd->name, name);
	}
    }
    return dcnd;
#else
    return (ErlDrvCond *) NULL;
#endif
}
예제 #13
0
ErlDrvMutex *
erl_drv_mutex_create(char *name)
{
#ifdef USE_THREADS
    ErlDrvMutex *dmtx = erts_alloc_fnf(ERTS_ALC_T_DRV_MTX,
				       (sizeof(ErlDrvMutex)
					+ (name ? sys_strlen(name) + 1 : 0)));
    if (dmtx) {
	if (ethr_mutex_init(&dmtx->mtx) != 0) {
	    erts_free(ERTS_ALC_T_DRV_MTX, (void *) dmtx);
	    dmtx = NULL;
	}
	else if (!name)
	    dmtx->name = no_name;
	else {
	    dmtx->name = ((char *) dmtx) + sizeof(ErlDrvMutex);
	    sys_strcpy(dmtx->name, name);
	}
    }
    return dmtx;
#else
    return (ErlDrvMutex *) NULL;
#endif
}
예제 #14
0
static Port *
open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump)
{
    Sint i;
    Eterm option;
    Uint arity;
    Eterm* tp;
    Uint* nargs;
    erts_driver_t* driver;
    char* name_buf = NULL;
    SysDriverOpts opts;
    Sint linebuf;
    Eterm edir = NIL;
    byte dir[MAXPATHLEN];
    erts_aint32_t sflgs = 0;
    Port *port;

    /* These are the defaults */
    opts.packet_bytes = 0;
    opts.use_stdio = 1;
    opts.redir_stderr = 0;
    opts.read_write = 0;
    opts.hide_window = 0;
    opts.wd = NULL;
    opts.envir = NULL;
    opts.exit_status = 0;
    opts.overlapped_io = 0; 
    opts.spawn_type = ERTS_SPAWN_ANY; 
    opts.argv = NULL;
    opts.parallelism = erts_port_parallelism;
    linebuf = 0;

    *err_nump = 0;

    if (is_not_list(settings) && is_not_nil(settings)) {
	goto badarg;
    }
    /*
     * Parse the settings.
     */

    if (is_not_nil(settings)) {
	nargs = list_val(settings);
	while (1) {
	    if (is_tuple_arity(*nargs, 2)) {
		tp = tuple_val(*nargs);
		arity = *tp++;
		option = *tp++;
		if (option == am_packet) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    opts.packet_bytes = signed_val(*tp);
		    switch (opts.packet_bytes) {
		    case 1:
		    case 2:
		    case 4:
			break;
		    default:
			goto badarg;
		   }
		} else if (option == am_line) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    linebuf = signed_val(*tp);
		    if (linebuf <= 0) {
			goto badarg;
		    }
		} else if (option == am_env) {
		    byte* bytes;
		    if ((bytes = convert_environment(p, *tp)) == NULL) {
			goto badarg;
		    }
		    opts.envir = (char *) bytes;
		} else if (option == am_args) {
		    char **av;
		    char **oav = opts.argv;
		    if ((av = convert_args(*tp)) == NULL) {
			goto badarg;
		    }
		    opts.argv = av;
		    if (oav) {
			opts.argv[0] = oav[0];
			oav[0] = erts_default_arg0;
			free_args(oav);
		    }

		} else if (option == am_arg0) {
		    char *a0;

		    if ((a0 = erts_convert_filename_to_native(*tp, NULL, 0, ERTS_ALC_T_TMP, 1, 1, NULL)) == NULL) {
			goto badarg;
		    }
		    if (opts.argv == NULL) {
			opts.argv = erts_alloc(ERTS_ALC_T_TMP, 
					       2 * sizeof(char **));
			opts.argv[0] = a0;
			opts.argv[1] = NULL;
		    } else {
			if (opts.argv[0] != erts_default_arg0) {
			    erts_free(ERTS_ALC_T_TMP, opts.argv[0]);
			}
			opts.argv[0] = a0;
		    }
		} else if (option == am_cd) {
		    edir = *tp;
		} else if (option == am_parallelism) {
		    if (*tp == am_true)
			opts.parallelism = 1;
		    else if (*tp == am_false)
			opts.parallelism = 0;
		    else
			goto badarg;
		} else {
		    goto badarg;
		}
	    } else if (*nargs == am_stream) {
		opts.packet_bytes = 0;
	    } else if (*nargs == am_use_stdio) {
		opts.use_stdio = 1;
	    } else if (*nargs == am_stderr_to_stdout) {
		opts.redir_stderr = 1;
	    } else if (*nargs == am_line) {
		linebuf = 512;
	    } else if (*nargs == am_nouse_stdio) {
		opts.use_stdio = 0;
	    } else if (*nargs == am_binary) {
		sflgs |= ERTS_PORT_SFLG_BINARY_IO;
	    } else if (*nargs == am_in) {
		opts.read_write |= DO_READ;
	    } else if (*nargs == am_out) {
		opts.read_write |= DO_WRITE;
	    } else if (*nargs == am_eof) {
		sflgs |= ERTS_PORT_SFLG_SOFT_EOF;
	    } else if (*nargs == am_hide) {
		opts.hide_window = 1;
	    } else if (*nargs == am_exit_status) {
		opts.exit_status = 1;
	    } else if (*nargs == am_overlapped_io) {
		opts.overlapped_io = 1;
	    } else {
		goto badarg;
	    }
	    if (is_nil(*++nargs)) 
		break;
	    if (is_not_list(*nargs)) {
		goto badarg;
	    }
	    nargs = list_val(*nargs);
	}
    }
    if (opts.read_write == 0)	/* implement default */
	opts.read_write = DO_READ|DO_WRITE;

    /* Mutually exclusive arguments. */
    if((linebuf && opts.packet_bytes) || 
       (opts.redir_stderr && !opts.use_stdio)) {
	goto badarg;
    }

    /*
     * Parse the first argument and start the appropriate driver.
     */
    
    if (is_atom(name) || (i = is_string(name))) {
	/* a vanilla port */
	if (is_atom(name)) {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					   atom_tab(atom_val(name))->len+1);
	    sys_memcpy((void *) name_buf,
		       (void *) atom_tab(atom_val(name))->name, 
		       atom_tab(atom_val(name))->len);
	    name_buf[atom_tab(atom_val(name))->len] = '\0';
	} else {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
	    if (intlist_to_buf(name, name_buf, i) != i)
		erts_exit(ERTS_ERROR_EXIT, "%s:%d: Internal error\n", __FILE__, __LINE__);
	    name_buf[i] = '\0';
	}
	driver = &vanilla_driver;
    } else {   
	if (is_not_tuple(name)) {
	    goto badarg;		/* Not a process or fd port */
	}
	tp = tuple_val(name);
	arity = *tp++;

	if (arity == make_arityval(0)) {
	    goto badarg;
	}
    
	if (*tp == am_spawn || *tp == am_spawn_driver || *tp == am_spawn_executable) {	/* A process port */
	    int encoding;
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    encoding = erts_get_native_filename_encoding();
	    /* Do not convert the command to utf-16le yet, do that in win32 specific code */
	    /* since the cmd is used for comparsion with drivers names and copied to port info */
	    if (encoding == ERL_FILENAME_WIN_WCHAR) {
		encoding = ERL_FILENAME_UTF8;
	    }
	    if ((name_buf = erts_convert_filename_to_encoding(name, NULL, 0, ERTS_ALC_T_TMP,0,1, encoding, NULL, 0))
		== NULL) {
		goto badarg;
	    }

	    if (*tp == am_spawn_driver) {
		opts.spawn_type = ERTS_SPAWN_DRIVER;
	    } else if (*tp == am_spawn_executable) {
		opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
	    }

	    driver = &spawn_driver;
	} else if (*tp == am_fd) { /* An fd port */
	    int n;
	    struct Sint_buf sbuf;
	    char* p;

	    if (arity != make_arityval(3)) {
		goto badarg;
	    }
	    if (is_not_small(tp[1]) || is_not_small(tp[2])) {
		goto badarg;
	    }
	    opts.ifd = unsigned_val(tp[1]);
	    opts.ofd = unsigned_val(tp[2]);

	    /* Syntesize name from input and output descriptor. */
	    name_buf = erts_alloc(ERTS_ALC_T_TMP,
				  2*sizeof(struct Sint_buf) + 2); 
	    p = Sint_to_buf(opts.ifd, &sbuf);
	    n = sys_strlen(p);
	    sys_strncpy(name_buf, p, n);
	    name_buf[n] = '/';
	    p = Sint_to_buf(opts.ofd, &sbuf);
	    sys_strcpy(name_buf+n+1, p);

	    driver = &fd_driver;
	} else {
	    goto badarg;
	}
    }

    if ((driver != &spawn_driver && opts.argv != NULL) ||
	(driver == &spawn_driver && 
	 opts.spawn_type != ERTS_SPAWN_EXECUTABLE && 
	 opts.argv != NULL)) {
	/* Argument vector only if explicit spawn_executable */
	goto badarg;
    }

    if (edir != NIL) {
	if ((opts.wd = erts_convert_filename_to_native(edir, NULL, 0, ERTS_ALC_T_TMP,0,1,NULL)) == NULL) {
	    goto badarg;
	}
    }

    if (driver != &spawn_driver && opts.exit_status) {
	goto badarg;
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_sched(p, ERTS_PROC_LOCK_MAIN, am_out);
    }
    

    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);

    port = erts_open_driver(driver, p->common.id, name_buf, &opts, err_typep, err_nump);
#ifdef USE_VM_PROBES
    if (port && DTRACE_ENABLED(port_open)) {
        DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
        DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);

        dtrace_proc_str(p, process_str);
        erts_snprintf(port_str, sizeof(DTRACE_CHARBUF_NAME(port_str)), "%T", port->common.id);
        DTRACE3(port_open, process_str, name_buf, port_str);
    }
#endif

    if (port && IS_TRACED_FL(port, F_TRACE_PORTS))
        trace_port(port, am_getting_linked, p->common.id);

    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);

    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_sched(p, ERTS_PROC_LOCK_MAIN, am_in);
    }

    if (!port) {
	DEBUGF(("open_driver returned (%d:%d)\n",
		err_typep ? *err_typep : 4711,
		err_nump ? *err_nump : 4711));
	goto do_return;
    }

    if (linebuf && port->linebuf == NULL){
	port->linebuf = allocate_linebuf(linebuf);
	sflgs |= ERTS_PORT_SFLG_LINEBUF_IO;
    }

    if (sflgs)
	erts_atomic32_read_bor_relb(&port->state, sflgs);
 
 do_return:
    if (name_buf)
	erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
    if (opts.argv) {
	free_args(opts.argv);
    }
    if (opts.wd && opts.wd != ((char *)dir)) {
	erts_free(ERTS_ALC_T_TMP, (void *) opts.wd);
    }
    return port;
    
 badarg:
    if (err_typep)
	*err_typep = -3;
    if (err_nump)
	*err_nump = BADARG;
    port = NULL;
    goto do_return;
}
예제 #15
0
int
erl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key)
{
    char *name_copy;
    Uint old_used_tsd_keys_len;
    ErlDrvTSDKey res;

    if (!key)
	fatal_error(EINVAL, "erl_drv_tsd_key_create()");

    if (!name)
	name_copy = no_name;
    else {
	name_copy = erts_alloc_fnf(ERTS_ALC_T_DRV_TSD,
				   sizeof(char)*(strlen(name) + 1));
	if (!name_copy) {
	    *key = -1;
	    return ENOMEM;
	}
	sys_strcpy(name_copy, name);
    }

    erts_mtx_lock(&tsd_mtx);

    *key = next_tsd_key;

    if (next_tsd_key < 0)
	res = ENOMEM;
    else {
	res = 0;

	ASSERT(!used_tsd_keys[next_tsd_key]);
	used_tsd_keys[next_tsd_key] = name_copy;

	if (max_used_tsd_key < next_tsd_key)
	    max_used_tsd_key = next_tsd_key;

	if (max_used_tsd_key + 1 >= used_tsd_keys_len) {
	    int i;
	    old_used_tsd_keys_len = used_tsd_keys_len;
	    if (used_tsd_keys_len + ERL_DRV_TSD_KEYS_INC >= INT_MAX) 
		next_tsd_key = -1;
	    else {
		char **new_used_tsd_keys;
		used_tsd_keys_len += ERL_DRV_TSD_KEYS_INC;
		new_used_tsd_keys = erts_realloc_fnf(ERTS_ALC_T_DRV_TSD,
						     used_tsd_keys,
						     (sizeof(char *)
						      * used_tsd_keys_len));
		if (!new_used_tsd_keys)
		    next_tsd_key = -1;
		else {
		    used_tsd_keys = new_used_tsd_keys;
		    for (i = old_used_tsd_keys_len; i < used_tsd_keys_len; i++)
			used_tsd_keys[i] = NULL;
		}
	    }
	}

	if (next_tsd_key >= 0) {
	    do {
		next_tsd_key++;
	    } while (used_tsd_keys[next_tsd_key]);
	}
	ASSERT(next_tsd_key < used_tsd_keys_len);
    }

    erts_mtx_unlock(&tsd_mtx);

    return res;
}
예제 #16
0
static int do_load_driver_entry(DE_Handle *dh, char *path, char *name)
{
    void *init_handle;
    int res;
    ErlDrvEntry *dp;

    assert_drv_list_rwlocked();

    if ((res =  erts_sys_ddll_open(path, &(dh->handle), NULL)) != ERL_DE_NO_ERROR) {
	return res;
    }
    
    if ((res = erts_sys_ddll_load_driver_init(dh->handle, 
					      &init_handle)) != ERL_DE_NO_ERROR) {
	res = ERL_DE_LOAD_ERROR_NO_INIT;
	goto error;
    }
    
    dp = erts_sys_ddll_call_init(init_handle);
    if (dp == NULL) {
	res = ERL_DE_LOAD_ERROR_FAILED_INIT;
	goto error;
    }

    switch (dp->extended_marker) {
    case ERL_DRV_EXTENDED_MARKER:
	if (dp->major_version < ERL_DRV_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD
	    || (ERL_DRV_EXTENDED_MAJOR_VERSION < dp->major_version
		|| (ERL_DRV_EXTENDED_MAJOR_VERSION == dp->major_version
		    && ERL_DRV_EXTENDED_MINOR_VERSION < dp->minor_version))) {
	    /* Incompatible driver version */
	    res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
	    goto error;
	}
	break;
    default:
	/* Old driver; needs to be recompiled... */
	res = ERL_DE_LOAD_ERROR_INCORRECT_VERSION;
	goto error;
    }

    if (strcmp(name, dp->driver_name) != 0) {
	res = ERL_DE_LOAD_ERROR_BAD_NAME;
	goto error;
    }
    erts_atomic_init_nob(&(dh->refc), (erts_aint_t) 0);
    erts_atomic32_init_nob(&dh->port_count, 0);
    dh->full_path = erts_alloc(ERTS_ALC_T_DDLL_HANDLE, sys_strlen(path) + 1);
    sys_strcpy(dh->full_path, path);
    dh->flags = 0;
    dh->status = ERL_DE_OK;

    if (erts_add_driver_entry(dp, dh, 1) != 0 /* io.c */) { 
	/*
	 * The init in the driver struct did not return 0 
	 */
	erts_free(ERTS_ALC_T_DDLL_HANDLE, dh->full_path);
	dh->full_path = NULL;
	res = ERL_DE_LOAD_ERROR_FAILED_INIT;
	goto error;
    }
    return ERL_DE_NO_ERROR;

error:
    erts_sys_ddll_close(dh->handle);
    return res;
}
예제 #17
0
파일: erl_bif_port.c 프로젝트: Korn1699/otp
static int
open_port(Process* p, Eterm name, Eterm settings, int *err_nump)
{
#define OPEN_PORT_ERROR(VAL) do { port_num = (VAL); goto do_return; } while (0)
    int i, port_num;
    Eterm option;
    Uint arity;
    Eterm* tp;
    Uint* nargs;
    erts_driver_t* driver;
    char* name_buf = NULL;
    SysDriverOpts opts;
    int binary_io;
    int soft_eof;
    Sint linebuf;
    Eterm edir = NIL;
    byte dir[MAXPATHLEN];

    /* These are the defaults */
    opts.packet_bytes = 0;
    opts.use_stdio = 1;
    opts.redir_stderr = 0;
    opts.read_write = 0;
    opts.hide_window = 0;
    opts.wd = NULL;
    opts.envir = NULL;
    opts.exit_status = 0;
    opts.overlapped_io = 0; 
    opts.spawn_type = ERTS_SPAWN_ANY; 
    opts.argv = NULL;
    binary_io = 0;
    soft_eof = 0;
    linebuf = 0;

    *err_nump = 0;

    if (is_not_list(settings) && is_not_nil(settings)) {
	goto badarg;
    }
    /*
     * Parse the settings.
     */

    if (is_not_nil(settings)) {
	nargs = list_val(settings);
	while (1) {
	    if (is_tuple_arity(*nargs, 2)) {
		tp = tuple_val(*nargs);
		arity = *tp++;
		option = *tp++;
		if (option == am_packet) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    opts.packet_bytes = signed_val(*tp);
		    switch (opts.packet_bytes) {
		    case 1:
		    case 2:
		    case 4:
			break;
		    default:
			goto badarg;
		   }
		} else if (option == am_line) {
		    if (is_not_small(*tp)) {
			goto badarg;
		    }
		    linebuf = signed_val(*tp);
		    if (linebuf <= 0) {
			goto badarg;
		    }
		} else if (option == am_env) {
		    byte* bytes;
		    if ((bytes = convert_environment(p, *tp)) == NULL) {
			goto badarg;
		    }
		    opts.envir = (char *) bytes;
		} else if (option == am_args) {
		    char **av;
		    char **oav = opts.argv;
		    if ((av = convert_args(*tp)) == NULL) {
			goto badarg;
		    }
		    opts.argv = av;
		    if (oav) {
			opts.argv[0] = oav[0];
			oav[0] = erts_default_arg0;
			free_args(oav);
		    }

		} else if (option == am_arg0) {
		    char *a0;

		    if ((a0 = erts_convert_filename_to_native(*tp, ERTS_ALC_T_TMP, 1)) == NULL) {
			goto badarg;
		    }
		    if (opts.argv == NULL) {
			opts.argv = erts_alloc(ERTS_ALC_T_TMP, 
					       2 * sizeof(char **));
			opts.argv[0] = a0;
			opts.argv[1] = NULL;
		    } else {
			if (opts.argv[0] != erts_default_arg0) {
			    erts_free(ERTS_ALC_T_TMP, opts.argv[0]);
			}
			opts.argv[0] = a0;
		    }
		} else if (option == am_cd) {
		    edir = *tp;
		} else {
		    goto badarg;
		}
	    } else if (*nargs == am_stream) {
		opts.packet_bytes = 0;
	    } else if (*nargs == am_use_stdio) {
		opts.use_stdio = 1;
	    } else if (*nargs == am_stderr_to_stdout) {
		opts.redir_stderr = 1;
	    } else if (*nargs == am_line) {
		linebuf = 512;
	    } else if (*nargs == am_nouse_stdio) {
		opts.use_stdio = 0;
	    } else if (*nargs == am_binary) {
		binary_io = 1;
	    } else if (*nargs == am_in) {
		opts.read_write |= DO_READ;
	    } else if (*nargs == am_out) {
		opts.read_write |= DO_WRITE;
	    } else if (*nargs == am_eof) {
		soft_eof = 1;
	    } else if (*nargs == am_hide) {
		opts.hide_window = 1;
	    } else if (*nargs == am_exit_status) {
		opts.exit_status = 1;
	    } else if (*nargs == am_overlapped_io) {
		opts.overlapped_io = 1;
	    } else {
		goto badarg;
	    }
	    if (is_nil(*++nargs)) 
		break;
	    if (is_not_list(*nargs)) {
		goto badarg;
	    }
	    nargs = list_val(*nargs);
	}
    }
    if (opts.read_write == 0)	/* implement default */
	opts.read_write = DO_READ|DO_WRITE;

    /* Mutually exclusive arguments. */
    if((linebuf && opts.packet_bytes) || 
       (opts.redir_stderr && !opts.use_stdio)) {
	goto badarg;
    }

    /*
     * Parse the first argument and start the appropriate driver.
     */
    
    if (is_atom(name) || (i = is_string(name))) {
	/* a vanilla port */
	if (is_atom(name)) {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					   atom_tab(atom_val(name))->len+1);
	    sys_memcpy((void *) name_buf,
		       (void *) atom_tab(atom_val(name))->name, 
		       atom_tab(atom_val(name))->len);
	    name_buf[atom_tab(atom_val(name))->len] = '\0';
	} else {
	    name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
	    if (intlist_to_buf(name, name_buf, i) != i)
		erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
	    name_buf[i] = '\0';
	}
	driver = &vanilla_driver;
    } else {   
	if (is_not_tuple(name)) {
	    goto badarg;		/* Not a process or fd port */
	}
	tp = tuple_val(name);
	arity = *tp++;

	if (arity == make_arityval(0)) {
	    goto badarg;
	}
    
	if (*tp == am_spawn || *tp == am_spawn_driver) {	/* A process port */
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    if (is_atom(name)) {
		name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP,
					       atom_tab(atom_val(name))->len+1);
		sys_memcpy((void *) name_buf,
			   (void *) atom_tab(atom_val(name))->name, 
			   atom_tab(atom_val(name))->len);
		name_buf[atom_tab(atom_val(name))->len] = '\0';
	    } else if ((i = is_string(name))) {
		name_buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
		if (intlist_to_buf(name, name_buf, i) != i)
		    erl_exit(1, "%s:%d: Internal error\n", __FILE__, __LINE__);
		name_buf[i] = '\0';
	    } else {
		goto badarg;
	    }
	    if (*tp == am_spawn_driver) {
		opts.spawn_type = ERTS_SPAWN_DRIVER;
	    }
	    driver = &spawn_driver;
	} else if (*tp == am_spawn_executable) {	/* A program */
	    /*
	     * {spawn_executable,Progname}
	     */
	    
	    if (arity != make_arityval(2)) {
		goto badarg;
	    }
	    name = tp[1];
	    if ((name_buf = erts_convert_filename_to_native(name,ERTS_ALC_T_TMP,0)) == NULL) {
		goto badarg;
	    }
	    opts.spawn_type = ERTS_SPAWN_EXECUTABLE;
	    driver = &spawn_driver;
	} else if (*tp == am_fd) { /* An fd port */
	    int n;
	    struct Sint_buf sbuf;
	    char* p;

	    if (arity != make_arityval(3)) {
		goto badarg;
	    }
	    if (is_not_small(tp[1]) || is_not_small(tp[2])) {
		goto badarg;
	    }
	    opts.ifd = unsigned_val(tp[1]);
	    opts.ofd = unsigned_val(tp[2]);

	    /* Syntesize name from input and output descriptor. */
	    name_buf = erts_alloc(ERTS_ALC_T_TMP,
				  2*sizeof(struct Sint_buf) + 2); 
	    p = Sint_to_buf(opts.ifd, &sbuf);
	    n = sys_strlen(p);
	    sys_strncpy(name_buf, p, n);
	    name_buf[n] = '/';
	    p = Sint_to_buf(opts.ofd, &sbuf);
	    sys_strcpy(name_buf+n+1, p);

	    driver = &fd_driver;
	} else {
	    goto badarg;
	}
    }

    if ((driver != &spawn_driver && opts.argv != NULL) ||
	(driver == &spawn_driver && 
	 opts.spawn_type != ERTS_SPAWN_EXECUTABLE && 
	 opts.argv != NULL)) {
	/* Argument vector only if explicit spawn_executable */
	goto badarg;
    }

    if (edir != NIL) {
	/* A working directory is expressed differently if spawn_executable, i.e. Unicode is handles 
	   for spawn_executable... */
	if (opts.spawn_type != ERTS_SPAWN_EXECUTABLE) {
	    Eterm iolist;
	    DeclareTmpHeap(heap,4,p);
	    int r;
	    
	    UseTmpHeap(4,p);
	    heap[0] = edir;
	    heap[1] = make_list(heap+2);
	    heap[2] = make_small(0);
	    heap[3] = NIL;
	    iolist = make_list(heap);
	    r = io_list_to_buf(iolist, (char*) dir, MAXPATHLEN);
	    UnUseTmpHeap(4,p);
	    if (r < 0) {
		goto badarg;
	    }
	    opts.wd = (char *) dir;
	} else {
	    if ((opts.wd = erts_convert_filename_to_native(edir,ERTS_ALC_T_TMP,0)) == NULL) {
		goto badarg;
	    }
	}
    }

    if (driver != &spawn_driver && opts.exit_status) {
	goto badarg;
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_virtual_sched(p, am_out);
    }
    

    erts_smp_proc_unlock(p, ERTS_PROC_LOCK_MAIN);

    port_num = erts_open_driver(driver, p->id, name_buf, &opts, err_nump);
#ifdef USE_VM_PROBES
    if (port_num >= 0 && DTRACE_ENABLED(port_open)) {
        DTRACE_CHARBUF(process_str, DTRACE_TERM_BUF_SIZE);
        DTRACE_CHARBUF(port_str, DTRACE_TERM_BUF_SIZE);

        dtrace_proc_str(p, process_str);
        erts_snprintf(port_str, sizeof(port_str), "%T", erts_port[port_num].id);
        DTRACE3(port_open, process_str, name_buf, port_str);
    }
#endif
    erts_smp_proc_lock(p, ERTS_PROC_LOCK_MAIN);

    if (port_num < 0) {
	DEBUGF(("open_driver returned %d(%d)\n", port_num, *err_nump));
    	if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
            trace_virtual_sched(p, am_in);
    	}
	OPEN_PORT_ERROR(port_num);
    }
    
    if (IS_TRACED_FL(p, F_TRACE_SCHED_PROCS)) {
        trace_virtual_sched(p, am_in);
    }

    if (binary_io) {
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_BINARY_IO);
    }
    if (soft_eof) {
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_SOFT_EOF);
    }
    if (linebuf && erts_port[port_num].linebuf == NULL){
	erts_port[port_num].linebuf = allocate_linebuf(linebuf); 
	erts_port_status_bor_set(&erts_port[port_num],
				 ERTS_PORT_SFLG_LINEBUF_IO);
    }
 
 do_return:
    if (name_buf)
	erts_free(ERTS_ALC_T_TMP, (void *) name_buf);
    if (opts.argv) {
	free_args(opts.argv);
    }
    if (opts.wd && opts.wd != ((char *)dir)) {
	erts_free(ERTS_ALC_T_TMP, (void *) opts.wd);
    }
    return port_num;
    
 badarg:
    *err_nump = BADARG;
    OPEN_PORT_ERROR(-3);
    goto do_return;
#undef OPEN_PORT_ERROR
}
예제 #18
0
/*
 * Try to load. If the driver is OK, add as LOADED.  If the driver is
 * UNLOAD, possibly change to reload and add as LOADED, 
 * there should be no other
 * LOADED tagged pid's.  If the driver is RELOAD then add/increment as
 * LOADED (should be some LOADED pid).  If the driver is not present,
 * really load and add as LOADED {ok,loaded} {ok,pending_driver}
 * {error, permanent} {error,load_error()}
 */
BIF_RETTYPE erl_ddll_try_load_3(BIF_ALIST_3)
{
    Eterm path_term = BIF_ARG_1;
    Eterm name_term = BIF_ARG_2;
    Eterm options = BIF_ARG_3;
    char *path = NULL;
    Sint path_len;
    char *name = NULL;
    DE_Handle *dh;
    erts_driver_t *drv;
    int res;
    Eterm soft_error_term = NIL;
    Eterm ok_term = NIL;
    Eterm *hp;
    Eterm t;
    int monitor = 0;
    int reload = 0;
    Eterm l;
    Uint flags = 0;
    int kill_ports = 0;
    int do_build_load_error = 0;
    int build_this_load_error = 0;
    int encoding;

    for(l = options; is_list(l); l =  CDR(list_val(l))) {
	Eterm opt = CAR(list_val(l));
	Eterm *tp;
	if (is_not_tuple(opt)) {
	    goto error;
	}
	tp = tuple_val(opt);
	if (*tp != make_arityval(2) || is_not_atom(tp[1])) {
	    goto error;
	}
	switch (tp[1]) {
	case am_driver_options:
	    {
		Eterm ll;
		for(ll = tp[2]; is_list(ll); ll = CDR(list_val(ll))) {
		    Eterm dopt = CAR(list_val(ll));
		    if (dopt == am_kill_ports) {
			flags |= ERL_DE_FL_KILL_PORTS;
		    } else {
			goto error;
		    }
		}
		if (is_not_nil(ll)) {
		    goto error;
		}
	    }
	    break;
	case am_monitor:
	    if (tp[2] == am_pending_driver) {
		monitor = 1;
	    } else if (tp[2] == am_pending ) {
		monitor = 2;
	    } else {
		goto error;
	    }
	    break;
	case am_reload:
	    if (tp[2] == am_pending_driver) {
		reload = 1;
	    } else if (tp[2] == am_pending ) {
		reload = 2;
	    } else {
		goto error;
	    }
	    break;
	default:
	    goto error;
	}
    }
    if (is_not_nil(l)) {
	goto error;
    }


    if ((name = pick_list_or_atom(name_term)) == NULL) {
	goto error;
    }

    encoding = erts_get_native_filename_encoding();
    if (encoding == ERL_FILENAME_WIN_WCHAR) {
        /* Do not convert the lib name to utf-16le yet, do that in win32 specific code */
        /* since lib_name is used in error messages */
        encoding = ERL_FILENAME_UTF8;
    }
    path = erts_convert_filename_to_encoding(path_term, NULL, 0,
					     ERTS_ALC_T_DDLL_TMP_BUF, 1, 0,
					     encoding, &path_len,
					     sys_strlen(name) + 2); /* might need path separator */
    if (!path) {
	goto error;
    }
    ASSERT(path_len > 0 && path[path_len-1] == 0);
    while (--path_len > 0 && (path[path_len-1] == '\\' || path[path_len-1] == '/'))
	;
    path[path_len++] = '/';
    sys_strcpy(path+path_len,name);

    erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
    lock_drv_list();
    if ((drv = lookup_driver(name)) != NULL) {
	if (drv->handle == NULL) {
	    /* static_driver */
	    soft_error_term = am_linked_in_driver;
	    goto soft_error;
	} else {
	    dh = drv->handle;
	    if (dh->status == ERL_DE_OK) {
		int is_last = is_last_user(dh, BIF_P);
		if (reload == 1 && !is_last) {
		    /*Want reload if no other users, 
		      but there are others...*/
		    soft_error_term = am_pending_process;
		    goto soft_error;
		} 
		if (reload != 0) {
		    DE_ProcEntry *old;
		    if ((dh->flags & ERL_FL_CONSISTENT_MASK) != 
			(flags &  ERL_FL_CONSISTENT_MASK)) {
			soft_error_term = am_inconsistent;
			goto soft_error;
		    }
		    if ((old = find_proc_entry(dh, BIF_P,
					       ERL_DE_PROC_LOADED)) ==
			NULL) {
			soft_error_term = am_not_loaded_by_this_process;
			goto soft_error;
		    } else {
			remove_proc_entry(dh, old);
			erts_ddll_dereference_driver(dh);
			erts_free(ERTS_ALC_T_DDLL_PROCESS, old);
		    }
		    /* Reload requested and granted */
		    dereference_all_processes(dh);
		    set_driver_reloading(dh, BIF_P, path, name, flags);
		    if (dh->flags & ERL_DE_FL_KILL_PORTS) {
			kill_ports = 1;
		    }
		    ok_term = (reload == 1) ? am_pending_driver : 
			am_pending_process;
		} else {
		    /* Already loaded and healthy (might be by me) */
		    if (sys_strcmp(dh->full_path, path) || 
			(dh->flags & ERL_FL_CONSISTENT_MASK) != 
			(flags &  ERL_FL_CONSISTENT_MASK)) {
			soft_error_term = am_inconsistent;
			goto soft_error;
		    }
		    add_proc_loaded(dh, BIF_P);
		    erts_ddll_reference_driver(dh);
		    monitor = 0;
		    ok_term = mkatom("already_loaded");
		}
	    } else if (dh->status == ERL_DE_UNLOAD ||
		       dh->status == ERL_DE_FORCE_UNLOAD) {
		/* pending driver */
		if (reload != 0) {
		    soft_error_term = am_not_loaded_by_this_process;
		    goto soft_error;
		} 
		if (sys_strcmp(dh->full_path, path) || 
		    (dh->flags & ERL_FL_CONSISTENT_MASK) != 
		    (flags &  ERL_FL_CONSISTENT_MASK)) {
		    soft_error_term = am_inconsistent;
		    goto soft_error;
		}
		dh->status = ERL_DE_OK;
		notify_all(dh, drv->name, 
			   ERL_DE_PROC_AWAIT_UNLOAD, am_UP, 
			   am_unload_cancelled);
		add_proc_loaded(dh, BIF_P);
		erts_ddll_reference_driver(dh);
		monitor = 0;
		ok_term = mkatom("already_loaded");
	    } else if (dh->status == ERL_DE_RELOAD ||
		       dh->status == ERL_DE_FORCE_RELOAD) {
		if (reload != 0) {
		    soft_error_term = am_pending_reload;
		    goto soft_error;
		}
		if (sys_strcmp(dh->reload_full_path, path) || 
		    (dh->reload_flags & ERL_FL_CONSISTENT_MASK) != 
		        (flags &  ERL_FL_CONSISTENT_MASK)) {
		    soft_error_term = am_inconsistent;
		    goto soft_error;
		}
		/* Load of granted unload... */
		/* Don't reference, will happen after reload */
		add_proc_loaded_deref(dh, BIF_P);
		++monitor;
		ok_term = am_pending_driver;
	    } else { /* ERL_DE_PERMANENT */
		soft_error_term = am_permanent;
		goto soft_error;
	    }
	}
    } else { /* driver non-existing */
	if (reload != 0) {
	    soft_error_term = am_not_loaded;
	    goto soft_error;
	} 
	if ((res = load_driver_entry(&dh, path, name)) !=  ERL_DE_NO_ERROR) {
	    build_this_load_error = res;
	    do_build_load_error = 1;
	    soft_error_term = am_undefined;
	    goto soft_error;
	} else {
	    dh->flags = flags;
	    add_proc_loaded(dh, BIF_P);
	    first_ddll_reference(dh);
	    monitor = 0;
	    ok_term = mkatom("loaded");
	}
    }
    assert_drv_list_rwlocked();
    if (kill_ports) {
 	/* Avoid closing the driver by referencing it */
	erts_ddll_reference_driver(dh);
	ASSERT(dh->status == ERL_DE_RELOAD);
	dh->status = ERL_DE_FORCE_RELOAD;
	unlock_drv_list();
	kill_ports_driver_unloaded(dh);
	/* Dereference, eventually causing driver destruction */
	lock_drv_list(); 
	erts_ddll_dereference_driver(dh);
    } 

    erts_ddll_reference_driver(dh);
    unlock_drv_list();
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    lock_drv_list();
    erts_ddll_dereference_driver(dh);

    BIF_P->flags |= F_USING_DDLL;
    if (monitor) {
	Eterm mref = add_monitor(BIF_P, dh, ERL_DE_PROC_AWAIT_LOAD);
	hp = HAlloc(BIF_P, 4);
	t = TUPLE3(hp, am_ok, ok_term, mref);
    } else {
	hp = HAlloc(BIF_P, 3);
	t = TUPLE2(hp, am_ok, ok_term);
    }
    unlock_drv_list();
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    BIF_RET(t);
 soft_error:
    unlock_drv_list();
    erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
    if (do_build_load_error) {
	soft_error_term = build_load_error(BIF_P, build_this_load_error);
    }

    hp = HAlloc(BIF_P, 3);
    t = TUPLE2(hp, am_error, soft_error_term);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    BIF_RET(t);
 error:
    assert_drv_list_not_locked();
    ERTS_LC_ASSERT(ERTS_PROC_LOCK_MAIN & erts_proc_lc_my_proc_locks(BIF_P));
    if (path != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) path);
    }
    if (name != NULL) {
	erts_free(ERTS_ALC_T_DDLL_TMP_BUF, (void *) name);
    }
    BIF_ERROR(BIF_P, BADARG);
}
예제 #19
0
/**
 * sys_strdup
 *
 * @brief
 *    This function returns a newly allocated copy of string.
 *
 * @param[in]    string         This is a pointer to the original string.
 *
 * @retval pointer to new string - on success
 * @retval NULL - on failure
 ***************************************************************************/
char *sys_strdup(const char *string)
{
	return string ?
		sys_strcpy((char *)sys_malloc(sys_strlen(string) + 1), string) :
		NULL;
}