aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/sys/unix/sys_drivers.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2015-10-14 09:56:03 +0200
committerLukas Larsson <[email protected]>2015-12-15 10:05:47 +0100
commit6fc7ccb41da5e9ec4357b40811ad740dd6a3b5b2 (patch)
tree156706b673d6ee9fd9d87b5fc11619e043f3ab34 /erts/emulator/sys/unix/sys_drivers.c
parentb96e62d346eea60b2300dce22d8d892387de4681 (diff)
downloadotp-6fc7ccb41da5e9ec4357b40811ad740dd6a3b5b2.tar.gz
otp-6fc7ccb41da5e9ec4357b40811ad740dd6a3b5b2.tar.bz2
otp-6fc7ccb41da5e9ec4357b40811ad740dd6a3b5b2.zip
erts: Only use forker StackAck on freebsd
Diffstat (limited to 'erts/emulator/sys/unix/sys_drivers.c')
-rw-r--r--erts/emulator/sys/unix/sys_drivers.c48
1 files changed, 33 insertions, 15 deletions
diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c
index dc1c00ff96..2a7cd91265 100644
--- a/erts/emulator/sys/unix/sys_drivers.c
+++ b/erts/emulator/sys/unix/sys_drivers.c
@@ -1762,17 +1762,13 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
ASSERT(res == sizeof(*proto));
+#ifdef FORKER_PROTO_START_ACK
if (proto->action == ErtsSysForkerProtoAction_StartAck) {
/* Ideally we would like to not have to ack each Start
command being sent over the uds, but it would seem
that some operating systems (only observed on FreeBSD)
throw away data on the uds when the socket becomes full,
so we have to.
-
- Also the freebsd manual explicitly states that
- you should not close fds before they are known
- to have reached the other side, so this Ack protects
- against that as well.
*/
ErlDrvPort port_num = (ErlDrvPort)e;
int vlen;
@@ -1788,7 +1784,9 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)
if (driver_sizeq(port_num) > 0)
driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);
- } else {
+ } else
+#endif
+ {
ASSERT(proto->action == ErtsSysForkerProtoAction_SigChld);
/* ideally this would be a port_command call, but as command is
@@ -1805,16 +1803,27 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)
{
ErlDrvPort port_num = (ErlDrvPort)e;
- int vlen;
- SysIOVec *iov = driver_peekq(port_num, &vlen);
- ErtsSysForkerProto *proto = (ErtsSysForkerProto *)iov[0].iov_base;
- ASSERT(iov[0].iov_len >= (sizeof(*proto)));
- if (sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
- proto->u.start.fds, 3, 0) < 0) {
- if (errno == ERRNO_BLOCK)
- return;
- erl_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup uds: %d", errno);
+#ifndef FORKER_PROTO_START_ACK
+ while (driver_sizeq(port_num) > 0) {
+#endif
+ int vlen;
+ SysIOVec *iov = driver_peekq(port_num, &vlen);
+ ErtsSysForkerProto *proto = (ErtsSysForkerProto *)iov[0].iov_base;
+ ASSERT(iov[0].iov_len >= (sizeof(*proto)));
+ if (sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),
+ proto->u.start.fds, 3, 0) < 0) {
+ if (errno == ERRNO_BLOCK)
+ return;
+ erl_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
+ }
+#ifndef FORKER_PROTO_START_ACK
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+ driver_deq(port_num, sizeof(*proto));
}
+#endif
driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);
}
@@ -1840,5 +1849,14 @@ static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf,
erl_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);
}
+#ifndef FORKER_PROTO_START_ACK
+ ASSERT(res == sizeof(*proto));
+ close(proto->u.start.fds[0]);
+ close(proto->u.start.fds[1]);
+ if (proto->u.start.fds[1] != proto->u.start.fds[2])
+ close(proto->u.start.fds[2]);
+ driver_deq(port_num, sizeof(*proto));
+#endif
+
return 0;
}