diff options
Diffstat (limited to 'erts/emulator')
| -rw-r--r-- | erts/emulator/beam/beam_ranges.c | 8 | ||||
| -rw-r--r-- | erts/emulator/beam/dist.c | 15 | ||||
| -rw-r--r-- | erts/emulator/beam/erl_alloc.c | 2 | ||||
| -rw-r--r-- | erts/emulator/beam/erl_bif_info.c | 28 | ||||
| -rw-r--r-- | erts/emulator/beam/ops.tab | 5 | ||||
| -rw-r--r-- | erts/emulator/sys/common/erl_poll.c | 17 | ||||
| -rw-r--r-- | erts/emulator/sys/unix/sys.c | 4 | ||||
| -rw-r--r-- | erts/emulator/sys/unix/sys_drivers.c | 107 | ||||
| -rw-r--r-- | erts/emulator/sys/unix/sys_uds.c | 13 | ||||
| -rw-r--r-- | erts/emulator/sys/win32/erl_poll.c | 18 | ||||
| -rw-r--r-- | erts/emulator/test/driver_SUITE.erl | 24 | ||||
| -rw-r--r-- | erts/emulator/test/map_SUITE.erl | 11 | 
12 files changed, 148 insertions, 104 deletions
| diff --git a/erts/emulator/beam/beam_ranges.c b/erts/emulator/beam/beam_ranges.c index f0c9496341..9f3153724a 100644 --- a/erts/emulator/beam/beam_ranges.c +++ b/erts/emulator/beam/beam_ranges.c @@ -35,10 +35,8 @@ typedef struct {  /*   * Used for crash dumping of literals. The size of erts_dump_lit_areas is - * always twice the number of active ranges (to allow for literals in both - * current and old code). + * always at least the number of active ranges.   */ -  ErtsLiteralArea** erts_dump_lit_areas;  Uint erts_dump_num_lit_areas; @@ -180,8 +178,8 @@ erts_end_staging_ranges(int commit)  				(erts_aint_t) (r[dst].modules +  					       r[dst].n / 2)); -        if (r[dst].allocated * 2 > erts_dump_num_lit_areas) { -            erts_dump_num_lit_areas *= 2; +        if (r[dst].allocated > erts_dump_num_lit_areas) { +            erts_dump_num_lit_areas = r[dst].allocated * 2;              erts_dump_lit_areas = (ErtsLiteralArea **)                  erts_realloc(ERTS_ALC_T_CRASH_DUMP,                               (void *) erts_dump_lit_areas, diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c index 70474898b2..61090e2c47 100644 --- a/erts/emulator/beam/dist.c +++ b/erts/emulator/beam/dist.c @@ -1200,21 +1200,8 @@ erts_dsig_send_group_leader(ErtsDSigData *dsdp, Eterm leader, Eterm remote)  #include <valgrind/valgrind.h>  #include <valgrind/memcheck.h> -#ifndef HAVE_VALGRIND_PRINTF_XML -#define VALGRIND_PRINTF_XML VALGRIND_PRINTF -#endif -  #  define PURIFY_MSG(msg)                                                    \ -    do {								     \ -	char buf__[1]; size_t bufsz__ = sizeof(buf__);			     \ -	if (erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf__, &bufsz__) >= 0) { \ -	    VALGRIND_PRINTF_XML("<erlang_error_log>"			     \ -			    "%s, line %d: %s</erlang_error_log>\n",	     \ -			    __FILE__, __LINE__, msg);			     \ -	} else {							     \ -	    VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg);     \ -	}								     \ -    } while (0) +    VALGRIND_PRINTF("%s, line %d: %s", __FILE__, __LINE__, msg)  #else  #  define PURIFY_MSG(msg)  #endif diff --git a/erts/emulator/beam/erl_alloc.c b/erts/emulator/beam/erl_alloc.c index 575d6ca867..8fe1ccb758 100644 --- a/erts/emulator/beam/erl_alloc.c +++ b/erts/emulator/beam/erl_alloc.c @@ -114,7 +114,7 @@ typedef union {      char align_afa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AFAllctr_t))];      AOFFAllctr_t aoffa;      char align_aoffa[ERTS_ALC_CACHE_LINE_ALIGN_SIZE(sizeof(AOFFAllctr_t))]; -} ErtsAllocatorState_t; +} ErtsAllocatorState_t erts_align_attribute(ERTS_CACHE_LINE_SIZE);  static ErtsAllocatorState_t std_alloc_state;  static ErtsAllocatorState_t ll_alloc_state; diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 5789fa8e71..7fada0d548 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -2093,17 +2093,6 @@ current_stacktrace(ErtsHeapFactory *hfact, Process* rp,      return res;  } -#if defined(VALGRIND) -static int check_if_xml(void) -{ -    char buf[1]; -    size_t bufsz = sizeof(buf); -    return erts_sys_explicit_8bit_getenv("VALGRIND_LOG_XML", buf, &bufsz) >= 0; -} -#else -#define check_if_xml() 0 -#endif -  /*   * This function takes care of calls to erlang:system_info/1 when the argument   * is a tuple. @@ -2200,15 +2189,9 @@ info_1_tuple(Process* BIF_P,	/* Pointer to current process. */  #endif  	} else if (is_list(*tp)) {  #if defined(PURIFY) -#define ERTS_ERROR_CHECKER_PRINTF purify_printf -#define ERTS_ERROR_CHECKER_PRINTF_XML purify_printf +#  define ERTS_ERROR_CHECKER_PRINTF purify_printf  #elif defined(VALGRIND) -#define ERTS_ERROR_CHECKER_PRINTF VALGRIND_PRINTF -#  ifndef HAVE_VALGRIND_PRINTF_XML -#    define ERTS_ERROR_CHECKER_PRINTF_XML VALGRIND_PRINTF -#  else -#    define ERTS_ERROR_CHECKER_PRINTF_XML VALGRIND_PRINTF_XML -#  endif +#  define ERTS_ERROR_CHECKER_PRINTF VALGRIND_PRINTF  #endif  	    ErlDrvSizeT buf_size = 8*1024; /* Try with 8KB first */  	    char *buf = erts_alloc(ERTS_ALC_T_TMP, buf_size); @@ -2224,12 +2207,7 @@ info_1_tuple(Process* BIF_P,	/* Pointer to current process. */  		ASSERT(r == buf_size - 1);  	    }  	    buf[buf_size - 1 - r] = '\0'; -	    if (check_if_xml()) { -		ERTS_ERROR_CHECKER_PRINTF_XML("<erlang_info_log>" -					      "%s</erlang_info_log>\n", buf); -	    } else { -		ERTS_ERROR_CHECKER_PRINTF("%s\n", buf); -	    } +            ERTS_ERROR_CHECKER_PRINTF("%s\n", buf);  	    erts_free(ERTS_ALC_T_TMP, (void *) buf);  	    BIF_RET(am_true);  #undef ERTS_ERROR_CHECKER_PRINTF diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab index 88ede3bb60..c51e4ef784 100644 --- a/erts/emulator/beam/ops.tab +++ b/erts/emulator/beam/ops.tab @@ -1421,16 +1421,13 @@ get_map_elements Fail Src Size Rest=* | map_key_sort(Size, Rest) => \  i_get_map_elements f? s I -i_get_map_element Fail Src=xy Key=y Dst => \ -    move Key x | i_get_map_element Fail Src x Dst -  i_get_map_element_hash Fail Src=c Key Hash Dst => \      move Src x | i_get_map_element_hash Fail x Key Hash Dst  i_get_map_element_hash f? xy c I xy  i_get_map_element Fail Src=c Key Dst => \      move Src x | i_get_map_element Fail x Key Dst -i_get_map_element f? xy x xy +i_get_map_element f? xy xy xy  #  # Convert the plus operations to a generic plus instruction. diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index 70b5532af9..b4d1575ee5 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -803,6 +803,23 @@ update_pollset(ErtsPollSet *ps, int fd, ErtsPollOp op, ErtsPollEvents events)      struct kevent evts[2];      struct timespec ts = {0, 0}; +    if (op == ERTS_POLL_OP_ADD) { +        /* This is a hack to make the "noshell" option work; kqueue can poll +         * these fds but will not report EV_EOF, so we return NVAL to use the +         * fallback instead. +         * +         * This may be common to all pipes but we have no way to tell whether +         * an fd is a pipe or not. */ +        switch (fd) { +        case STDIN_FILENO: +        case STDOUT_FILENO: +        case STDERR_FILENO: +            return ERTS_POLL_EV_NVAL; +        default: +            break; +        } +    } +  #if defined(EV_DISPATCH) && !defined(__OpenBSD__)      /* If we have EV_DISPATCH we use it, unless we are on OpenBSD as the         behavior of EV_EOF seems to be edge triggered there and we need it diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index 189ca083d7..36579ffdb4 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -452,9 +452,9 @@ prepare_crash_dump(int secs)      envsz = sizeof(env);      i = erts_sys_explicit_8bit_getenv("ERL_CRASH_DUMP_NICE", env, &envsz); -    if (i >= 0) { +    if (i != 0) {  	int nice_val; -	nice_val = i != 1 ? 0 : atoi(env); +	nice_val = (i != 1) ? 0 : atoi(env);  	if (nice_val > 39) {  	    nice_val = 39;  	} diff --git a/erts/emulator/sys/unix/sys_drivers.c b/erts/emulator/sys/unix/sys_drivers.c index 872c3a80b1..d0498f0bd5 100644 --- a/erts/emulator/sys/unix/sys_drivers.c +++ b/erts/emulator/sys/unix/sys_drivers.c @@ -685,7 +685,7 @@ static ErlDrvData spawn_start(ErlDrvPort port_num, char* name,          /* we send the request to do the fork */          if ((res = writev(ofd[1], io_vector, iov_len > MAXIOV ? MAXIOV : iov_len)) < 0) { -            if (errno == ERRNO_BLOCK) { +            if (errno == ERRNO_BLOCK || errno == EINTR) {                  res = 0;              } else {                  int err = errno; @@ -1257,6 +1257,8 @@ static int port_inp_failure(ErtsSysDriverData *dd, int res)          }         driver_failure_eof(dd->port_num);      } else if (dd->ifd) { +        if (dd->alive == -1) +            errno = dd->status;          erl_drv_init_ack(dd->port_num, ERL_DRV_ERROR_ERRNO);      } else {  	driver_failure_posix(dd->port_num, err); @@ -1287,10 +1289,10 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)          int res;          if((res = read(ready_fd, &proto, sizeof(proto))) <= 0) { +            if (res < 0 && (errno == ERRNO_BLOCK || errno == EINTR)) +                return;              /* hmm, child setup seems to have closed the pipe too early...                 we close the port as there is not much else we can do */ -            if (res < 0 && errno == ERRNO_BLOCK) -                return;              driver_select(port_num, ready_fd, ERL_DRV_READ, 0);              if (res == 0)                  errno = EPIPE; @@ -1424,7 +1426,7 @@ static void ready_input(ErlDrvData e, ErlDrvEvent ready_fd)  		    continue;  		}  		else {		/* The last message we got was split */ -		        char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h); +                    char *buf = erts_alloc_fnf(ERTS_ALC_T_FD_ENTRY_BUF, h);  		    if (!buf) {  			errno = ENOMEM;  			port_inp_failure(dd, -1); @@ -1670,15 +1672,37 @@ static void forker_stop(ErlDrvData e)         the port has been closed by the user. */  } +static ErlDrvSizeT forker_deq(ErlDrvPort port_num, ErtsSysForkerProto *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]); + +    return driver_deq(port_num, sizeof(*proto)); +} + +static void forker_sigchld(Eterm port_id, int error) +{ +    ErtsSysForkerProto *proto = erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA, sizeof(*proto)); +    proto->action = ErtsSysForkerProtoAction_SigChld; +    proto->u.sigchld.error_number = error; +    proto->u.sigchld.port_id = port_id; + +    /* ideally this would be a port_command call, but as command is +       already used by the spawn_driver, we use control instead. +       Note that when using erl_drv_port_control it is an asynchronous +       control. */ +    erl_drv_port_control(port_id, 'S', (char*)proto, sizeof(*proto)); +} +  static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)  {      int res; -    ErtsSysForkerProto *proto; +    ErtsSysForkerProto proto; -    proto = erts_alloc(ERTS_ALC_T_DRV_CTRL_DATA, sizeof(*proto)); - -    if ((res = read(fd, proto, sizeof(*proto))) < 0) { -        if (errno == ERRNO_BLOCK) +    if ((res = read(fd, &proto, sizeof(proto))) < 0) { +        if (errno == ERRNO_BLOCK || errno == EINTR)              return;          erts_exit(ERTS_DUMP_EXIT, "Failed to read from erl_child_setup: %d\n", errno);      } @@ -1686,10 +1710,10 @@ static void forker_ready_input(ErlDrvData e, ErlDrvEvent fd)      if (res == 0)          erts_exit(ERTS_DUMP_EXIT, "erl_child_setup closed\n"); -    ASSERT(res == sizeof(*proto)); +    ASSERT(res == sizeof(proto));  #ifdef FORKER_PROTO_START_ACK -    if (proto->action == ErtsSysForkerProtoAction_StartAck) { +    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) @@ -1699,28 +1723,15 @@ static void forker_ready_input(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; - -        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]); +        ErtsSysForkerProto *qproto = (ErtsSysForkerProto *)iov[0].iov_base; -        driver_deq(port_num, sizeof(*proto)); - -        if (driver_sizeq(port_num) > 0) +        if (forker_deq(port_num, qproto))              driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);      } else  #endif      { -        ASSERT(proto->action == ErtsSysForkerProtoAction_SigChld); - -        /* ideally this would be a port_command call, but as command is -           already used by the spawn_driver, we use control instead. -           Note that when using erl_drv_port_control it is an asynchronous -           control. */ -        erl_drv_port_control(proto->u.sigchld.port_id, 'S', -                             (char*)proto, sizeof(*proto)); +        ASSERT(proto.action == ErtsSysForkerProtoAction_SigChld); +        forker_sigchld(proto.u.sigchld.port_id, proto.u.sigchld.error_number);      }  } @@ -1730,7 +1741,8 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)      ErlDrvPort port_num = (ErlDrvPort)e;  #ifndef FORKER_PROTO_START_ACK -    while (driver_sizeq(port_num) > 0) { +    int loops = 10; +    while (driver_sizeq(port_num) > 0 && --loops) {  #endif          int vlen;          SysIOVec *iov = driver_peekq(port_num, &vlen); @@ -1738,20 +1750,24 @@ static void forker_ready_output(ErlDrvData e, ErlDrvEvent fd)          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) +            if (errno == ERRNO_BLOCK || errno == EINTR) {                  return; -            erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno); +            } else if (errno == EMFILE) { +                forker_sigchld(proto->u.start.port_id, errno); +                if (forker_deq(port_num, proto) == 0) +                    driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0); +                return; +            } else { +                erts_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)); +        if (forker_deq(port_num, proto) == 0) +            driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0);      } -#endif - +#else      driver_select(port_num, forker_fd, ERL_DRV_WRITE, 0); +#endif  }  static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf, @@ -1777,20 +1793,21 @@ static ErlDrvSSizeT forker_control(ErlDrvData e, unsigned int cmd, char *buf,      if ((res = sys_uds_write(forker_fd, (char*)proto, sizeof(*proto),                               proto->u.start.fds, 3, 0)) < 0) { -        if (errno == ERRNO_BLOCK) { +        if (errno == ERRNO_BLOCK || errno == EINTR) {              driver_select(port_num, forker_fd, ERL_DRV_WRITE|ERL_DRV_USE, 1);              return 0; +        } else if (errno == EMFILE) { +            forker_sigchld(proto->u.start.port_id, errno); +            forker_deq(port_num, proto); +            return 0; +        } else { +            erts_exit(ERTS_DUMP_EXIT, "Failed to write to erl_child_setup: %d\n", errno);          } -        erts_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)); +    forker_deq(port_num, proto);  #endif      return 0; diff --git a/erts/emulator/sys/unix/sys_uds.c b/erts/emulator/sys/unix/sys_uds.c index c328fd00bb..39a4866065 100644 --- a/erts/emulator/sys/unix/sys_uds.c +++ b/erts/emulator/sys/unix/sys_uds.c @@ -132,7 +132,7 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,      struct msghdr msg;      struct cmsghdr *cmsg = NULL; -    int res, i; +    int res, i, error;      /* initialize socket message */      memset(&msg, 0, sizeof(struct msghdr)); @@ -173,11 +173,22 @@ sys_uds_writev(int fd, struct iovec *iov, size_t iov_len,      res = sendmsg(fd, &msg, flags); +#ifdef ETOOMANYREFS +    /* Linux may give ETOOMANYREFS when there are too many fds in transit. +       We map this to EMFILE as bsd and other use this error code and we want +       the behaviour to be the same on all OSs */ +    if (errno == ETOOMANYREFS) +        errno = EMFILE; +#endif +    error = errno; +      if (iov_len > MAXIOV)          free(iov[0].iov_base);      free(msg.msg_control); +    errno = error; +      return res;  } diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c index fd4c745c3b..fcf5a0d533 100644 --- a/erts/emulator/sys/win32/erl_poll.c +++ b/erts/emulator/sys/win32/erl_poll.c @@ -362,11 +362,11 @@ is_io_ready(ErtsPollSet *ps)  }  static ERTS_INLINE void -woke_up(ErtsPollSet *ps) +woke_up(ErtsPollSet *ps, int waketype)  {      if (erts_atomic32_read_nob(&ps->wakeup_state) == ERTS_POLL_NOT_WOKEN)  	erts_atomic32_cmpxchg_nob(&ps->wakeup_state, -				  ERTS_POLL_WOKEN_TIMEDOUT, +				  waketype,  				  ERTS_POLL_NOT_WOKEN);  #ifdef DEBUG      { @@ -960,12 +960,12 @@ static int cancel_driver_select(ErtsPollSet *ps, HANDLE event)  void  erts_poll_interrupt(ErtsPollSet *ps, int set /* bool */)  { -    HARDTRACEF(("In erts_poll_interrupt(%d)",set)); +    HARDTRACEF(("In erts_poll_interrupt(%p, %d)",ps,set));      if (!set)  	reset_interrupt(ps);      else  	set_interrupt(ps); -    HARDTRACEF(("Out erts_poll_interrupt(%d)",set)); +    HARDTRACEF(("Out erts_poll_interrupt(%p, %d)",ps,set));  } @@ -1051,19 +1051,20 @@ int erts_poll_wait(ErtsPollSet *ps,      if (!erts_atomic32_read_nob(&break_waiter_state)) {  	HANDLE harr[2] = {ps->event_io_ready, break_happened_event}; -	int num_h = 2; +	int num_h = 2, handle;          ERTS_MSACC_PUSH_STATE();  	HARDDEBUGF(("Start waiting %d [%d]",num_h, (int) timeout));  	ERTS_POLLSET_UNLOCK(ps);  	erts_thr_progress_prepare_wait(NULL);          ERTS_MSACC_SET_STATE_CACHED(ERTS_MSACC_STATE_SLEEP); -	WaitForMultipleObjects(num_h, harr, FALSE, timeout); +	handle = WaitForMultipleObjects(num_h, harr, FALSE, timeout);  	erts_thr_progress_finalize_wait(NULL);          ERTS_MSACC_POP_STATE();  	ERTS_POLLSET_LOCK(ps);  	HARDDEBUGF(("Stop waiting %d [%d]",num_h, (int) timeout)); -	woke_up(ps); +        if (handle == WAIT_OBJECT_0) +            woke_up(ps, ERTS_POLL_WOKEN_TIMEDOUT);      }      ERTS_UNSET_BREAK_REQUESTED; @@ -1075,7 +1076,10 @@ int erts_poll_wait(ErtsPollSet *ps,  	erts_mtx_unlock(&break_waiter_lock);  	switch (break_state) {  	case  BREAK_WAITER_GOT_BREAK: +            woke_up(ps, ERTS_POLL_WOKEN_INTR);  	    ERTS_SET_BREAK_REQUESTED; +            /* Wake aux thread to get handle break */ +            erts_aux_thread_poke();  	    break;  	case  BREAK_WAITER_GOT_HALT:  	    erts_exit(0,""); diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index 7aff3a6ea1..6f5d639d04 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -81,6 +81,7 @@           thr_msg_blast/1,           consume_timeslice/1,           env/1, +         poll_pipe/1,           z_test/1]).  -export([bin_prefix/2]). @@ -168,6 +169,7 @@ all() -> %% Keep a_test first and z_test last...       thr_msg_blast,       consume_timeslice,       env, +     poll_pipe,       z_test].  groups() ->  @@ -2693,3 +2695,25 @@ rpc(Config, Fun) ->                      ct:fail(Other)              end      end. + +poll_pipe(Config) when is_list(Config) -> +    %% ERL-647; we wouldn't see any events on EOF when polling a pipe using +    %% kqueue(2). +    case os:type() of +        {unix, _} -> +            Command = "erl -noshell -eval " +                      "'\"DATA\n\" = io:get_line(\"\")," +                      "eof = io:get_line(\"\")," +                      "halt()' <<< 'DATA'", +            Ref = make_ref(), +            Self = self(), +            Pid = spawn(fun() -> os:cmd(Command), Self ! Ref end), +            receive +                Ref -> ok +            after 5000 -> +                exit(Pid, kill), +                ct:fail("Stuck reading from stdin.") +            end; +        _ -> +            {skipped, "Unix-only test"} +    end. diff --git a/erts/emulator/test/map_SUITE.erl b/erts/emulator/test/map_SUITE.erl index f93c637650..d0a6763fe5 100644 --- a/erts/emulator/test/map_SUITE.erl +++ b/erts/emulator/test/map_SUITE.erl @@ -3080,8 +3080,19 @@ y_regs(Config) when is_list(Config) ->      true = is_map(Map2) andalso is_map(Map4), +    gurka = y_regs_literal(0), +    gaffel = y_regs_literal(1), +      ok. +y_regs_literal(Key) when is_integer(Key) -> +    %% Forces the key to be placed in a Y register. +    lists:seq(1, 2), +    case is_map_key(Key, #{ 0 => 0 }) of +        true -> gurka; +        false -> gaffel +    end. +  y_regs_update(Map0, Val0) ->      Val1 = {t,Val0},      K1 = id({key,1}), | 
