aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorRickard Green <rickard@erlang.org>2013-11-28 15:04:25 +0100
committerRickard Green <rickard@erlang.org>2013-11-28 15:04:25 +0100
commit0519e57f544a2dc1f60e5524d000f2211fc029e8 (patch)
treeeee3727caa22f87504b26f6983259454ade7d826 /erts
parent7914f4c8e64a3b9a4fdf94aa65150705b7da08b7 (diff)
parentdc9ff931423b57e64abde0f1de7133f334abb780 (diff)
downloadotp-0519e57f544a2dc1f60e5524d000f2211fc029e8.tar.gz
otp-0519e57f544a2dc1f60e5524d000f2211fc029e8.tar.bz2
otp-0519e57f544a2dc1f60e5524d000f2211fc029e8.zip
Merge branch 'rickard/port_bifs_fix/OTP-11489' into maint
* rickard/port_bifs_fix/OTP-11489: Ensure exit signal due to link precede port BIF return
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erlang.xml162
-rw-r--r--erts/emulator/beam/bif.c37
-rw-r--r--erts/emulator/beam/erl_bif_port.c34
-rw-r--r--erts/emulator/beam/erl_port_task.h11
-rw-r--r--erts/emulator/beam/io.c2
5 files changed, 198 insertions, 48 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index cbb25c2cf2..062caadad3 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -3032,7 +3032,10 @@ os_prompt% </pre>
(see below), being synchronous, and that the port does
<em>not</em> reply with <c>{Port, closed}</c>. Any process may
close a port with <c>port_close/1</c>, not only the port owner
- (the connected process).</p>
+ (the connected process). If the calling process is linked to
+ port identified by <c><anno>Port</anno></c>, an exit signal due
+ to that link will be received by the process prior to the return
+ from <c>port_close/1</c>.</p>
<p>For comparison: <c><anno>Port</anno> ! {self(), close}</c> fails with
<c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to (i.e.,
<c><anno>Port</anno></c> refers neither to a port nor to a process). If
@@ -3041,6 +3044,7 @@ os_prompt% </pre>
the port replies with <c>{Port, closed}</c> when all buffers
have been flushed and the port really closes, but if
the calling process is not the port owner the <em>port owner</em> fails with <c>badsig</c>.</p>
+
<p>Note that any process can close a port using
<c><anno>Port</anno> ! {PortOwner, close}</c> just as if it itself was
the port owner, but the reply always goes to the port owner.</p>
@@ -3050,8 +3054,17 @@ os_prompt% </pre>
implementation has been synchronous. <c>port_close/1</c> is
however still fully synchronous. This due to its error
behavior.</p>
- <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port or
- the registered name of an open port.</p>
+ <p>Failure:</p>
+ <taglist>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Port</anno></c> is not an identifier of an open
+ port, or the registered name of an open port. If the calling
+ process was linked to the previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to this exception.
+ </item>
+ </taglist>
</desc>
</func>
<func>
@@ -3086,8 +3099,11 @@ os_prompt% </pre>
<taglist>
<tag><c>badarg</c></tag>
<item>
- If <c><anno>Port</anno></c> is not an open port or the registered name
- of an open port.
+ If <c><anno>Port</anno></c> is not an identifier of an open
+ port, or the registered name of an open port. If the calling
+ process was linked to the previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to this exception.
</item>
<tag><c>badarg</c></tag>
<item>
@@ -3130,8 +3146,11 @@ os_prompt% </pre>
<taglist>
<tag><c>badarg</c></tag>
<item>
- If <c><anno>Port</anno></c> is not an open port or the registered name
- of an open port.
+ If <c><anno>Port</anno></c> is not an identifier of an open
+ port, or the registered name of an open port. If the calling
+ process was linked to the previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to this exception.
</item>
<tag><c>badarg</c></tag>
<item>
@@ -3198,9 +3217,20 @@ os_prompt% </pre>
implementation has been synchronous. <c>port_connect/2</c> is
however still fully synchronous. This due to its error
behavior.</p>
- <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port
- or the registered name of an open port, or if <c>Pid</c> is
- not an existing local pid.</p>
+ <p>Failures:</p>
+ <taglist>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Port</anno></c> is not an identifier of an open
+ port, or the registered name of an open port. If the calling
+ process was linked to the previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to this exception.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>If process identified by <c>Pid</c> is not an existing
+ local process.</item>
+ </taglist>
</desc>
</func>
<func>
@@ -3236,12 +3266,33 @@ os_prompt% </pre>
binary term format and sent to the port.</p>
<p>Returns: a term from the driver. The meaning of the returned
data also depends on the port driver.</p>
- <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port or
- the registered name of an open port, if <c><anno>Operation</anno></c>
- cannot fit in a 32-bit integer, if the port driver does not
- support synchronous control operations, or if the port driver
- so decides for any reason (probably something wrong with
- <c><anno>Operation</anno></c> or <c><anno>Data</anno></c>).</p>
+ <p>Failures:</p>
+ <taglist>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Port</anno></c> is not an identifier of an open
+ port, or the registered name of an open port. If the calling
+ process was linked to the previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to this exception.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If <c><anno>Operation</anno></c> does not fit in a
+ 32-bit integer.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If the port driver does not support synchronous control
+ operations.
+ </item>
+ <tag><c>badarg</c></tag>
+ <item>
+ If the port driver so decides for any reason (probably
+ something wrong with <c><anno>Operation</anno></c>, or
+ <c><anno>Data</anno></c>).
+ </item>
+ </taglist>
</desc>
</func>
<func>
@@ -3251,7 +3302,12 @@ os_prompt% </pre>
<p>Returns a list containing tuples with information about
the <c><anno>Port</anno></c>, or <c>undefined</c> if the port is not open.
The order of the tuples is not defined, nor are all the
- tuples mandatory.</p>
+ tuples mandatory.
+ If <c>undefined</c> is returned and the calling process
+ was linked to a previously open port identified by
+ <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/1</c>.</p>
<p>Currently the result will containt information about the
following <c>Item</c>s: <c>registered_name</c> (if the port has
a registered name), <c>id</c>, <c>connected</c>, <c>links</c>,
@@ -3269,7 +3325,11 @@ os_prompt% </pre>
<p><c><anno>Pid</anno></c> is the process identifier of the process
connected to the port.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3281,7 +3341,11 @@ os_prompt% </pre>
<p><c><anno>Index</anno></c> is the internal index of the port. This
index may be used to separate ports.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3293,7 +3357,11 @@ os_prompt% </pre>
<p><c><anno>Bytes</anno></c> is the total number of bytes
read from the port.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3305,7 +3373,11 @@ os_prompt% </pre>
<p><c><anno>Pids</anno></c> is a list of the process identifiers
of the processes that the port is linked to.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3320,7 +3392,11 @@ os_prompt% </pre>
that these results are highly implementation specific and might
change in the future.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3334,7 +3410,11 @@ os_prompt% </pre>
that the port itself might have allocated memory which is not
included in <c><anno>Bytes</anno></c>.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3346,7 +3426,11 @@ os_prompt% </pre>
<p><c><anno>Monitors</anno></c> represent processes that this port
is monitoring.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3358,7 +3442,11 @@ os_prompt% </pre>
<p><c><anno>Name</anno></c> is the command name set by
<seealso marker="#open_port/2">open_port/2</seealso>.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3373,7 +3461,11 @@ os_prompt% </pre>
Command}, Options)</seealso>. If the port is not the result of spawning
an OS process, the value is <c>undefined</c>.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3389,7 +3481,11 @@ os_prompt% </pre>
or <c><anno>Port</anno> ! {Owner, {command, Data}</c>.
</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3412,7 +3508,11 @@ os_prompt% </pre>
in bytes, queued by the port using the ERTS driver queue
implementation.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
@@ -3424,7 +3524,11 @@ os_prompt% </pre>
<p><c><anno>RegisteredName</anno></c> is the registered name of
the port. If the port has no registered name, <c>[]</c> is returned.</p>
<p>If the port identified by <c><anno>Port</anno></c> is not open,
- <c>undefined</c> is returned.</p>
+ <c>undefined</c> is returned. If <c>undefined</c> is returned and
+ the calling process was linked to a previously open port identified
+ by <c><anno>Port</anno></c>, an exit signal due to this link
+ was received by the process prior to the return from
+ <c>port_info/2</c>.</p>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local
port identifier, or an atom.</p>
</desc>
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 755c5e6882..13d31285b2 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -160,7 +160,10 @@ BIF_RETTYPE link_1(BIF_ALIST_1)
if (is_internal_port(BIF_ARG_1)) {
int send_link_signal = 0;
- Port *prt = erts_port_lookup(BIF_ARG_1, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ Port *prt = erts_port_lookup(BIF_ARG_1,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (!prt) {
goto res_no_proc;
}
@@ -1363,11 +1366,22 @@ BIF_RETTYPE exit_2(BIF_ALIST_2)
*/
if (is_internal_port(BIF_ARG_1)) {
- Port *prt = erts_port_lookup(BIF_ARG_1, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ Eterm ref, *refp;
+ Uint32 invalid_flags;
+ Port *prt;
+
+ if (erts_port_synchronous_ops) {
+ refp = &ref;
+ invalid_flags = ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP;
+ }
+ else {
+ refp = NULL;
+ invalid_flags = ERTS_PORT_SFLGS_INVALID_LOOKUP;
+ }
+
+ prt = erts_port_lookup(BIF_ARG_1, invalid_flags);
if (prt) {
- Eterm ref;
- Eterm *refp = erts_port_synchronous_ops ? &ref : NULL;
ErtsPortOpResult res;
#ifdef DEBUG
@@ -1875,7 +1889,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
if (rp)
goto send_message;
- pt = erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(id,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (pt) {
portid = id;
goto port_common;
@@ -1905,7 +1922,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
int ret_val;
portid = to;
- pt = erts_port_lookup(portid, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(portid,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
port_common:
ret_val = 0;
@@ -1994,7 +2014,10 @@ do_send(Process *p, Eterm to, Eterm msg, int suspend, Eterm *refp) {
rp = erts_proc_lookup_raw(id);
if (rp)
goto send_message;
- pt = erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ pt = erts_port_lookup(id,
+ (erts_port_synchronous_ops
+ ? ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP
+ : ERTS_PORT_SFLGS_INVALID_LOOKUP));
if (pt) {
portid = id;
goto port_common;
diff --git a/erts/emulator/beam/erl_bif_port.c b/erts/emulator/beam/erl_bif_port.c
index 109c54fd7f..3cd53ef65d 100644
--- a/erts/emulator/beam/erl_bif_port.c
+++ b/erts/emulator/beam/erl_bif_port.c
@@ -84,7 +84,7 @@ BIF_RETTYPE open_port_2(BIF_ALIST_2)
}
static ERTS_INLINE Port *
-lookup_port(Process *c_p, Eterm id_or_name)
+lookup_port(Process *c_p, Eterm id_or_name, Uint32 invalid_flags)
{
/* TODO: Implement nicer lookup in register... */
Eterm id;
@@ -92,7 +92,19 @@ lookup_port(Process *c_p, Eterm id_or_name)
id = erts_whereis_name_to_id(c_p, id_or_name);
else
id = id_or_name;
- return erts_port_lookup(id, ERTS_PORT_SFLGS_INVALID_LOOKUP);
+ return erts_port_lookup(id, invalid_flags);
+}
+
+static ERTS_INLINE Port *
+sig_lookup_port(Process *c_p, Eterm id_or_name)
+{
+ return lookup_port(c_p, id_or_name, ERTS_PORT_SFLGS_INVALID_DRIVER_LOOKUP);
+}
+
+static ERTS_INLINE Port *
+data_lookup_port(Process *c_p, Eterm id_or_name)
+{
+ return lookup_port(c_p, id_or_name, ERTS_PORT_SFLGS_INVALID_LOOKUP);
}
/*
@@ -125,7 +137,7 @@ BIF_RETTYPE erts_internal_port_command_3(BIF_ALIST_3)
BIF_RET(am_badarg);
}
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -185,7 +197,7 @@ BIF_RETTYPE erts_internal_port_call_3(BIF_ALIST_3)
unsigned int op;
erts_aint32_t state;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -235,7 +247,7 @@ BIF_RETTYPE erts_internal_port_control_3(BIF_ALIST_3)
unsigned int op;
erts_aint32_t state;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -290,7 +302,7 @@ BIF_RETTYPE erts_internal_port_close_1(BIF_ALIST_1)
ref = NIL;
#endif
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -320,7 +332,7 @@ BIF_RETTYPE erts_internal_port_connect_2(BIF_ALIST_2)
Eterm ref;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_badarg);
@@ -352,7 +364,7 @@ BIF_RETTYPE erts_internal_port_info_1(BIF_ALIST_1)
Port* prt;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_undefined);
}
@@ -391,7 +403,7 @@ BIF_RETTYPE erts_internal_port_info_2(BIF_ALIST_2)
Port* prt;
if (is_internal_port(BIF_ARG_1) || is_atom(BIF_ARG_1)) {
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = sig_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_RET(am_undefined);
}
@@ -523,7 +535,7 @@ BIF_RETTYPE port_set_data_2(BIF_ALIST_2)
erts_aint_t data;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = data_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_ERROR(BIF_P, BADARG);
@@ -564,7 +576,7 @@ BIF_RETTYPE port_get_data_1(BIF_ALIST_1)
erts_aint_t data;
Port* prt;
- prt = lookup_port(BIF_P, BIF_ARG_1);
+ prt = data_lookup_port(BIF_P, BIF_ARG_1);
if (!prt)
BIF_ERROR(BIF_P, BADARG);
diff --git a/erts/emulator/beam/erl_port_task.h b/erts/emulator/beam/erl_port_task.h
index e4d964146e..123253a057 100644
--- a/erts/emulator/beam/erl_port_task.h
+++ b/erts/emulator/beam/erl_port_task.h
@@ -77,6 +77,7 @@ extern erts_smp_atomic_t erts_port_task_outstanding_io_tasks;
#define ERTS_PTS_FLG_HAVE_NS_TASKS (((erts_aint32_t) 1) << 8)
#define ERTS_PTS_FLG_PARALLELISM (((erts_aint32_t) 1) << 9)
#define ERTS_PTS_FLG_FORCE_SCHED (((erts_aint32_t) 1) << 10)
+#define ERTS_PTS_FLG_EXITING (((erts_aint32_t) 1) << 11)
#define ERTS_PTS_FLGS_BUSY \
(ERTS_PTS_FLG_BUSY_PORT | ERTS_PTS_FLG_BUSY_PORT_Q)
@@ -86,7 +87,8 @@ extern erts_smp_atomic_t erts_port_task_outstanding_io_tasks;
| ERTS_PTS_FLG_HAVE_BUSY_TASKS \
| ERTS_PTS_FLG_HAVE_TASKS \
| ERTS_PTS_FLG_EXEC \
- | ERTS_PTS_FLG_FORCE_SCHED)
+ | ERTS_PTS_FLG_FORCE_SCHED \
+ | ERTS_PTS_FLG_EXITING)
#define ERTS_PORT_TASK_DEFAULT_BUSY_PORT_Q_HIGH 8192
#define ERTS_PORT_TASK_DEFAULT_BUSY_PORT_Q_LOW 4096
@@ -135,6 +137,7 @@ ERTS_GLB_INLINE void erts_port_task_fini_sched(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE void erts_port_task_sched_lock(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE void erts_port_task_sched_unlock(ErtsPortTaskSched *ptsp);
ERTS_GLB_INLINE int erts_port_task_sched_lock_is_locked(ErtsPortTaskSched *ptsp);
+ERTS_GLB_INLINE void erts_port_task_sched_enter_exiting_state(ErtsPortTaskSched *ptsp);
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS
ERTS_GLB_INLINE int erts_port_task_have_outstanding_io_tasks(void);
@@ -225,6 +228,12 @@ erts_port_task_fini_sched(ErtsPortTaskSched *ptsp)
#endif
}
+ERTS_GLB_INLINE void
+erts_port_task_sched_enter_exiting_state(ErtsPortTaskSched *ptsp)
+{
+ erts_smp_atomic32_read_bor_nob(&ptsp->flags, ERTS_PTS_FLG_EXITING);
+}
+
#ifdef ERTS_INCLUDE_SCHEDULER_INTERNALS
ERTS_GLB_INLINE int
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 6911fd8241..9076bbe73c 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -3601,6 +3601,8 @@ erts_deliver_port_exit(Port *p, Eterm from, Eterm reason, int send_closed)
if (send_closed)
set_state_flags |= ERTS_PORT_SFLG_SEND_CLOSED;
+ erts_port_task_sched_enter_exiting_state(&p->sched);
+
state = erts_atomic32_read_bor_mb(&p->state, set_state_flags);
state |= set_state_flags;