aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
Diffstat (limited to 'erts')
-rw-r--r--erts/doc/src/erlang.xml4
-rw-r--r--erts/emulator/beam/atom.names1
-rw-r--r--erts/emulator/beam/erl_bif_info.c16
-rw-r--r--erts/emulator/beam/global.h1
-rw-r--r--erts/emulator/beam/io.c1
-rw-r--r--erts/emulator/sys/unix/sys.c2
-rw-r--r--erts/emulator/test/port_bif_SUITE.erl28
7 files changed, 51 insertions, 2 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 30e3b02a0a..3664bdf76d 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -3084,6 +3084,10 @@ os_prompt%</pre>
<p><c><anno>Bytes</anno></c> is the total number of bytes written to
the port.</p>
</item>
+ <tag><c>{os_pid, Integer}</c></tag>
+ <item>
+ <p><c>Integer</c> is the OS pid of the spawned process (Unix systems only).</p>
+ </item>
</taglist>
<p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local port.</p>
</desc>
diff --git a/erts/emulator/beam/atom.names b/erts/emulator/beam/atom.names
index 7be40976f6..2c6e80a3c3 100644
--- a/erts/emulator/beam/atom.names
+++ b/erts/emulator/beam/atom.names
@@ -390,6 +390,7 @@ atom opt
atom or
atom ordered_set
atom orelse
+atom os_pid
atom os_type
atom os_version
atom ose_bg_proc
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index ebd475f73a..e198be67c7 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -2741,7 +2741,8 @@ port_info_1(BIF_ALIST_1)
am_id,
am_connected,
am_input,
- am_output
+ am_output,
+ am_os_pid
};
Eterm items[ASIZE(keys)];
Eterm result = NIL;
@@ -2798,6 +2799,7 @@ port_info_1(BIF_ALIST_1)
** name String
** input Number of bytes input from port program
** output Number of bytes output to the port program
+** os_pid The child's process ID
*/
BIF_RETTYPE port_info_2(BIF_ALIST_2)
@@ -2898,6 +2900,18 @@ static BIF_RETTYPE port_info(Process* p, Eterm portid, Eterm item)
hp = HAlloc(p, hsz);
res = erts_bld_uint(&hp, NULL, n);
}
+ else if (item == am_os_pid) {
+ if (prt->os_pid >= 0) {
+ Uint hsz = 3;
+ Uint n = prt->os_pid;
+ (void) erts_bld_uint(NULL, &hsz, n);
+ hp = HAlloc(p, hsz);
+ res = erts_bld_uint(&hp, NULL, n);
+ } else {
+ hp = HAlloc(p, 3);
+ res = am_undefined;
+ }
+ }
else if (item == am_registered_name) {
RegProc *reg;
reg = prt->reg;
diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h
index 6eac0db363..1431e08610 100644
--- a/erts/emulator/beam/global.h
+++ b/erts/emulator/beam/global.h
@@ -174,6 +174,7 @@ struct port {
char *name; /* String used in the open */
erts_driver_t* drv_ptr;
UWord drv_data;
+ pid_t os_pid; /* Child process ID */
ErtsProcList *suspended; /* List of suspended processes. */
LineBuf *linebuf; /* Buffer to hold data not ready for
process to get (line oriented I/O)*/
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index b23b1f628d..3deb386621 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -425,6 +425,7 @@ setup_port(Port* prt, Eterm pid, erts_driver_t *driver,
sys_strcpy(new_name, name);
erts_smp_runq_lock(runq);
erts_smp_port_state_lock(prt);
+ prt->os_pid = -1;
prt->status = ERTS_PORT_SFLG_CONNECTED | xstatus;
prt->snapshot = erts_smp_atomic32_read_nob(&erts_ports_snapshot);
old_name = prt->name;
diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c
index f94e0f2296..bf69f3bf90 100644
--- a/erts/emulator/sys/unix/sys.c
+++ b/erts/emulator/sys/unix/sys.c
@@ -1163,6 +1163,8 @@ static int set_driver_data(int port_num,
report_exit_list = report_exit;
}
+ erts_port[port_num].os_pid = pid;
+
if (read_write & DO_READ) {
driver_data[ifd].packet_bytes = packet_bytes;
driver_data[ifd].port_num = port_num;
diff --git a/erts/emulator/test/port_bif_SUITE.erl b/erts/emulator/test/port_bif_SUITE.erl
index d9c82aba0e..f4ba502be5 100644
--- a/erts/emulator/test/port_bif_SUITE.erl
+++ b/erts/emulator/test/port_bif_SUITE.erl
@@ -24,6 +24,7 @@
init_per_group/2,end_per_group/2, command/1,
command_e_1/1, command_e_2/1, command_e_3/1, command_e_4/1,
port_info1/1, port_info2/1,
+ port_info_os_pid/1,
connect/1, control/1, echo_to_busy/1]).
-export([do_command_e_1/1, do_command_e_2/1, do_command_e_4/1]).
@@ -41,7 +42,7 @@ all() ->
groups() ->
[{command_e, [],
[command_e_1, command_e_2, command_e_3, command_e_4]},
- {port_info, [], [port_info1, port_info2]}].
+ {port_info, [], [port_info1, port_info2, port_info_os_pid]}].
init_per_suite(Config) ->
Config.
@@ -196,6 +197,7 @@ port_info1(Config) when is_list(Config) ->
?line {value,{connected,_}}=lists:keysearch(connected, 1, A),
?line {value,{input,0}}=lists:keysearch(input, 1, A),
?line {value,{output,0}}=lists:keysearch(output, 1, A),
+ ?line {value,{os_pid,undefined}}=lists:keysearch(os_pid, 1, A), % linked-in driver doesn't have a OS pid
?line true=erlang:port_close(P),
ok.
@@ -215,6 +217,7 @@ port_info2(Config) when is_list(Config) ->
?line {connected, Me} = erlang:port_info(P, connected),
?line {input, 0}=erlang:port_info(P, input),
?line {output,0}=erlang:port_info(P, output),
+ ?line {os_pid, undefined}=erlang:port_info(P, os_pid), % linked-in driver doesn't have a OS pid
?line erlang:port_control(P, $i, "abc"),
?line receive
@@ -229,6 +232,29 @@ port_info2(Config) when is_list(Config) ->
?line true = erlang:port_close(P),
ok.
+%% Tests the port_info/1,2 os_pid option BIF
+port_info_os_pid(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} ->
+ do_port_info_os_pid();
+ _ ->
+ {skip,"Only on Unix."}
+ end.
+
+do_port_info_os_pid() ->
+ ?line P = open_port({spawn, "echo $$"}, [eof]),
+ ?line A = erlang:port_info(P),
+ ?line {os_pid, InfoOSPid} = erlang:port_info(P, os_pid),
+ ?line EchoPidStr = receive
+ {P, {data, EchoPidStr0}} -> EchoPidStr0
+ after 10000 -> ?line test_server:fail(timeout)
+ end,
+ ?line {ok, [EchoPid], []} = io_lib:fread("~u\n", EchoPidStr),
+ ?line {value,{os_pid, InfoOSPid}}=lists:keysearch(os_pid, 1, A),
+ ?line EchoPid = InfoOSPid,
+ ?line true = erlang:port_close(P),
+ ok.
+
output_test(_, _, Input, Output) when Output > 16#1fffffff ->
io:format("~p bytes received\n", [Input]);
output_test(P, Bin, Input0, Output0) ->