aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/erl_bif_port.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-12-15 10:10:10 +0100
committerLukas Larsson <[email protected]>2015-12-15 10:21:40 +0100
commit9083bc7e2172937296b7e8fbe09ed595c6893f08 (patch)
treeb3b4255af12bf6cc023ee7a47bcf5ae5ae115077 /erts/emulator/beam/erl_bif_port.c
parentd7cd5ee8a34d289fbc91627a3f096a870bf70393 (diff)
parent4b1b3bf6c62f8208b2eea506c9dac1504df6e916 (diff)
downloadotp-9083bc7e2172937296b7e8fbe09ed595c6893f08.tar.gz
otp-9083bc7e2172937296b7e8fbe09ed595c6893f08.tar.bz2
otp-9083bc7e2172937296b7e8fbe09ed595c6893f08.zip
Merge branch 'lukas/erts/forker'
* lukas/erts/forker: (28 commits) erts: Never abort in the forked child erts: Mend ASSERT makro for erl_child_setup erts: Allow enomem failures in port_SUITE erts: iter_port sleep longer on freebsd erts: Allow one dangling fd if there is a gethost port erts: Only use forker StackAck on freebsd erts: It is not possible to exit the forker driver erts: Add forker StartAck for port start flowcontrol erts: Fix large open_port arg segfault for win32 erts: Fix memory leak at async open port kernel: Remove cmd server for unix os:cmd erts: Add testcase for huge port environment erts: Move os_pid to port hash to child setup erts: Handle all EINTR and EAGAIN cases in child setup erts: Make child_setup work with large environments erts: Fix forker driver ifdefs for win32 erts: Fix uds socket handling for os x erts: Fix dereferencing of unaligned integer for sparc erts: Flatten too long io vectors in uds write erts: Add fd count test for spawn_driver ... Conflicts: erts/emulator/beam/erl_node_tables.c erts/preloaded/src/erts_internal.erl
Diffstat (limited to 'erts/emulator/beam/erl_bif_port.c')
-rw-r--r--erts/emulator/beam/erl_bif_port.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index e47d7bcbbb..839abd0424 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -41,6 +41,7 @@
#include "external.h"
#include "packet_parser.h"
#include "erl_bits.h"
+#include "erl_bif_unique.h"
#include "dtrace-wrapper.h"
static Port *open_port(Process* p, Eterm name, Eterm settings, int *err_typep, int *err_nump);
@@ -50,10 +51,10 @@ static void free_args(char **);
char *erts_default_arg0 = "default";
-BIF_RETTYPE open_port_2(BIF_ALIST_2)
+BIF_RETTYPE erts_internal_open_port_2(BIF_ALIST_2)
{
Port *port;
- Eterm port_id;
+ Eterm res;
char *str;
int err_type, err_num;
@@ -61,27 +62,58 @@ BIF_RETTYPE open_port_2(BIF_ALIST_2)
if (!port) {
if (err_type == -3) {
ASSERT(err_num == BADARG || err_num == SYSTEM_LIMIT);
- BIF_ERROR(BIF_P, err_num);
+ if (err_num == BADARG)
+ res = am_badarg;
+ else if (err_num == SYSTEM_LIMIT)
+ res = am_system_limit;
+ else
+ /* this is only here to silence gcc, it should not happen */
+ BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
} else if (err_type == -2) {
str = erl_errno_id(err_num);
+ res = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1);
} else {
- str = "einval";
+ res = am_einval;
}
- BIF_P->fvalue = erts_atom_put((byte *) str, strlen(str), ERTS_ATOM_ENC_LATIN1, 1);
- BIF_ERROR(BIF_P, EXC_ERROR);
- }
+ BIF_RET(res);
+ }
+
+ if (port->drv_ptr->flags & ERL_DRV_FLAG_USE_INIT_ACK) {
+ /* Copied from erl_port_task.c */
+ port->async_open_port = erts_alloc(ERTS_ALC_T_PRTSD,
+ sizeof(*port->async_open_port));
+ erts_make_ref_in_array(port->async_open_port->ref);
+ port->async_open_port->to = BIF_P->common.id;
+
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK);
+ if (ERTS_PROC_PENDING_EXIT(BIF_P)) {
+ /* need to exit caller instead */
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE | ERTS_PROC_LOCK_LINK);
+ KILL_CATCHES(BIF_P);
+ BIF_P->freason = EXC_EXIT;
+ erts_port_release(port);
+ BIF_RET(am_badarg);
+ }
+
+ ERTS_SMP_MSGQ_MV_INQ2PRIVQ(BIF_P);
+ BIF_P->msg.save = BIF_P->msg.last;
- erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCKS_MSG_RECEIVE);
+
+ res = erts_proc_store_ref(BIF_P, port->async_open_port->ref);
+ } else {
+ res = port->common.id;
+ erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_LINK);
+ }
- port_id = port->common.id;
erts_add_link(&ERTS_P_LINKS(port), LINK_PID, BIF_P->common.id);
- erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port_id);
+ erts_add_link(&ERTS_P_LINKS(BIF_P), LINK_PID, port->common.id);
erts_smp_proc_unlock(BIF_P, ERTS_PROC_LOCK_LINK);
erts_port_release(port);
- BIF_RET(port_id);
+ BIF_RET(res);
}
static ERTS_INLINE Port *