diff options
Diffstat (limited to 'erts/emulator')
29 files changed, 338 insertions, 106 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index e6fbdc0d45..dd788df6e4 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -956,7 +956,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks, Eterm retval; int i; - if ((retval = beam_make_current_old(c_p, c_p_locks, module)) < 0) { + if ((retval = beam_make_current_old(c_p, c_p_locks, module)) != NIL) { erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf(); erts_dsprintf(dsbufp, "Module %T must be purged before loading\n", diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 143f631f58..58a09986d2 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -1507,6 +1507,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) Eterm ret = am_ok; int veto; struct erl_module_nif* lib = NULL; + int reload_warning = 0; len = list_length(BIF_ARG_1); if (len < 0) { @@ -1646,6 +1647,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) else { mod->nif->entry = NULL; /* to prevent 'unload' callback */ erts_unload_nif(mod->nif); + reload_warning = 1; } } else { @@ -1714,6 +1716,15 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2) erts_smp_thr_progress_unblock(); erts_smp_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN); erts_free(ERTS_ALC_T_TMP, lib_name); + + if (reload_warning) { + erts_dsprintf_buf_t* dsbufp = erts_create_logger_dsbuf(); + erts_dsprintf(dsbufp, + "Repeated calls to erlang:load_nif from module '%T'.\n\n" + "The NIF reload mechanism is deprecated and must not " + "be used in production systems.\n", mod_atom); + erts_send_warning_to_logger(BIF_P->group_leader, dsbufp); + } BIF_RET(ret); } diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index ec4b1dcd98..055211ad9b 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -909,7 +909,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, #ifdef ERTS_SMP if (awdp->async_ready.need_thr_prgr - && !erts_thr_progress_has_reached(awdp->misc.thr_prgr)) { + && !erts_thr_progress_has_reached(awdp->async_ready.thr_prgr)) { return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; } @@ -928,6 +928,7 @@ handle_async_ready_clean(ErtsAuxWorkData *awdp, erts_thr_progress_wakeup(awdp->esdp, awdp->async_ready.thr_prgr); awdp->async_ready.need_thr_prgr = 1; + return aux_work & ~ERTS_SSI_AUX_WORK_ASYNC_READY_CLEAN; #endif default: return aux_work; diff --git a/erts/emulator/beam/erl_time.h b/erts/emulator/beam/erl_time.h index 7a09d30ff6..6c6e193818 100644 --- a/erts/emulator/beam/erl_time.h +++ b/erts/emulator/beam/erl_time.h @@ -20,7 +20,11 @@ #ifndef ERL_TIME_H__ #define ERL_TIME_H__ -extern erts_smp_atomic_t do_time; /* set at clock interrupt */ +#define ERTS_SHORT_TIME_T_MAX ERTS_AINT32_T_MAX +#define ERTS_SHORT_TIME_T_MIN ERTS_AINT32_T_MIN +typedef erts_aint32_t erts_short_time_t; + +extern erts_smp_atomic32_t do_time; /* set at clock interrupt */ extern SysTimeval erts_first_emu_time; /* @@ -71,22 +75,32 @@ void erts_cancel_smp_ptimer(ErtsSmpPTimer *ptimer); void erts_init_time(void); void erts_set_timer(ErlTimer*, ErlTimeoutProc, ErlCancelProc, void*, Uint); void erts_cancel_timer(ErlTimer*); -void erts_bump_timer(erts_aint_t); +void erts_bump_timer(erts_short_time_t); Uint erts_timer_wheel_memory_size(void); Uint erts_time_left(ErlTimer *); -erts_aint_t erts_next_time(void); +erts_short_time_t erts_next_time(void); #ifdef DEBUG void erts_p_slpq(void); #endif -ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void); -ERTS_GLB_INLINE void erts_do_time_add(long); +ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void); +ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t); #if ERTS_GLB_INLINE_INCL_FUNC_DEF -ERTS_GLB_INLINE erts_aint_t erts_do_time_read_and_reset(void) { return erts_smp_atomic_xchg_acqb(&do_time, 0L); } -ERTS_GLB_INLINE void erts_do_time_add(long elapsed) { erts_smp_atomic_add_relb(&do_time, elapsed); } +ERTS_GLB_INLINE erts_short_time_t erts_do_time_read_and_reset(void) +{ + erts_short_time_t time = erts_smp_atomic32_xchg_acqb(&do_time, 0); + if (time < 0) + erl_exit(ERTS_ABORT_EXIT, "Internal time management error\n"); + return time; +} + +ERTS_GLB_INLINE void erts_do_time_add(erts_short_time_t elapsed) +{ + erts_smp_atomic32_add_relb(&do_time, elapsed); +} #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */ @@ -105,7 +119,7 @@ void erts_get_now_cpu(Uint* megasec, Uint* sec, Uint* microsec); #endif void erts_get_timeval(SysTimeval *tv); -long erts_get_time(void); +erts_time_t erts_get_time(void); void erts_get_emu_time(SysTimeval *); ERTS_GLB_INLINE int erts_cmp_timeval(SysTimeval *t1p, SysTimeval *t2p); diff --git a/erts/emulator/beam/erl_time_sup.c b/erts/emulator/beam/erl_time_sup.c index ed906f210d..f782e2f0b1 100644 --- a/erts/emulator/beam/erl_time_sup.c +++ b/erts/emulator/beam/erl_time_sup.c @@ -371,7 +371,7 @@ static void init_erts_deliver_time(const SysTimeval *inittv) static void do_erts_deliver_time(const SysTimeval *current) { SysTimeval cur_time; - long elapsed; + erts_time_t elapsed; /* calculate and deliver appropriate number of ticks */ cur_time = *current; @@ -385,7 +385,10 @@ static void do_erts_deliver_time(const SysTimeval *current) this by simply pretend as if the time stood still. :) */ if (elapsed > 0) { - erts_do_time_add(elapsed); + + ASSERT(elapsed < ((erts_time_t) ERTS_SHORT_TIME_T_MAX)); + + erts_do_time_add((erts_short_time_t) elapsed); last_delivered = cur_time; } } @@ -629,7 +632,7 @@ static int erl_mktime(time_t *c, struct tm *tm) { * greater of equal to 1600 , and month [1-12] and day [1-31] * are within range. Otherwise it returns -1. */ -static time_t gregday(Sint year, Sint month, Sint day) +static time_t gregday(int year, int month, int day) { Sint ndays = 0; Sint gyear, pyear, m; @@ -906,13 +909,14 @@ void erts_deliver_time(void) { void erts_time_remaining(SysTimeval *rem_time) { - int ticks; + erts_time_t ticks; SysTimeval cur_time; - long elapsed; + erts_time_t elapsed; /* erts_next_time() returns no of ticks to next timeout or -1 if none */ - if ((ticks = erts_next_time()) == -1) { + ticks = (erts_time_t) erts_next_time(); + if (ticks == (erts_time_t) -1) { /* timer queue empty */ /* this will cause at most 100000000 ticks */ rem_time->tv_sec = 100000; @@ -947,7 +951,7 @@ void erts_get_timeval(SysTimeval *tv) erts_smp_mtx_unlock(&erts_timeofday_mtx); } -long +erts_time_t erts_get_time(void) { SysTimeval sys_tv; diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index c2cc03509e..759621d3c2 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -644,7 +644,6 @@ erts_open_driver(erts_driver_t* driver, /* Pointer to driver. */ name, opts); erts_unblock_fpe(fpe_was_unmasked); port->caller = NIL; - erts_unblock_fpe(fpe_was_unmasked); if (IS_TRACED_FL(port, F_TRACE_SCHED_PORTS)) { trace_sched_ports_where(port, am_out, am_start); } diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c index a66d60aa22..4d4b6ea196 100644 --- a/erts/emulator/beam/packet_parser.c +++ b/erts/emulator/beam/packet_parser.c @@ -301,7 +301,11 @@ int packet_get_length(enum PacketParseType htype, /* TCP_PB_LINE_LF: [Data ... \n] */ const char* ptr2; if ((ptr2 = memchr(ptr, '\n', n)) == NULL) { - if (n >= trunc_len && trunc_len!=0) { /* buffer full */ + if (n > max_plen && max_plen != 0) { /* packet full */ + DEBUGF((" => packet full (no NL)=%d\r\n", n)); + goto error; + } + else if (n >= trunc_len && trunc_len!=0) { /* buffer full */ DEBUGF((" => line buffer full (no NL)=%d\r\n", n)); return trunc_len; } @@ -309,6 +313,10 @@ int packet_get_length(enum PacketParseType htype, } else { int len = (ptr2 - ptr) + 1; /* including newline */ + if (len > max_plen && max_plen!=0) { + DEBUGF((" => packet_size %d exceeded\r\n", max_plen)); + goto error; + } if (len > trunc_len && trunc_len!=0) { DEBUGF((" => truncated line=%d\r\n", trunc_len)); return trunc_len; @@ -397,33 +405,50 @@ int packet_get_length(enum PacketParseType htype, const char* ptr1 = ptr; int len = plen; + if (!max_plen) { + /* This is for backward compatibility with old user of decode_packet + * that might use option 'line_length' to limit accepted length of + * http lines. + */ + max_plen = trunc_len; + } + while (1) { const char* ptr2 = memchr(ptr1, '\n', len); if (ptr2 == NULL) { - if (n >= trunc_len && trunc_len!=0) { /* buffer full */ - plen = trunc_len; - goto done; + if (max_plen != 0) { + if (n >= max_plen) /* packet full */ + goto error; } goto more; } else { plen = (ptr2 - ptr) + 1; - - if (*statep == 0) + + if (*statep == 0) { + if (max_plen != 0 && plen > max_plen) + goto error; goto done; - + } + if (plen < n) { if (SP(ptr2+1) && plen>2) { /* header field value continue on next line */ ptr1 = ptr2+1; len = n - plen; } - else + else { + if (max_plen != 0 && plen > max_plen) + goto error; goto done; + } } - else + else { + if (max_plen != 0 && plen > max_plen) + goto error; goto more; + } } } } diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h index 038c319470..6b4b382caa 100644 --- a/erts/emulator/beam/sys.h +++ b/erts/emulator/beam/sys.h @@ -636,10 +636,11 @@ extern char *erts_sys_ddll_error(int code); /* * System interfaces for startup. */ +#include "erl_time.h" void erts_sys_schedule_interrupt(int set); #ifdef ERTS_SMP -void erts_sys_schedule_interrupt_timed(int set, long msec); +void erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec); void erts_sys_main_thread(void); #endif diff --git a/erts/emulator/beam/time.c b/erts/emulator/beam/time.c index db9a24e0a3..932d157cd8 100644 --- a/erts/emulator/beam/time.c +++ b/erts/emulator/beam/time.c @@ -107,20 +107,31 @@ static ErlTimer *tiw_min_ptr; /* Actual interval time chosen by sys_init_time() */ static int itime; /* Constant after init */ -erts_smp_atomic_t do_time; /* set at clock interrupt */ -static ERTS_INLINE erts_aint_t do_time_read(void) { return erts_smp_atomic_read_acqb(&do_time); } -static ERTS_INLINE erts_aint_t do_time_update(void) { return do_time_read(); } -static ERTS_INLINE void do_time_init(void) { erts_smp_atomic_init_nob(&do_time, 0L); } +erts_smp_atomic32_t do_time; /* set at clock interrupt */ +static ERTS_INLINE erts_short_time_t do_time_read(void) +{ + return erts_smp_atomic32_read_acqb(&do_time); +} + +static ERTS_INLINE erts_short_time_t do_time_update(void) +{ + return do_time_read(); +} + +static ERTS_INLINE void do_time_init(void) +{ + erts_smp_atomic32_init_nob(&do_time, 0); +} /* get the time (in units of itime) to the next timeout, or -1 if there are no timeouts */ -static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ +static erts_short_time_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ { int i, tm, nto; - unsigned int min; + Uint32 min; ErlTimer* p; - erts_aint_t dt; + erts_short_time_t dt; if (tiw_nto == 0) return -1; /* no timeouts in wheel */ @@ -133,7 +144,7 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ /* start going through wheel to find next timeout */ tm = nto = 0; - min = (unsigned int) -1; /* max unsigned int */ + min = (Uint32) -1; /* max Uint32 */ i = tiw_pos; do { p = tiw[i]; @@ -162,7 +173,11 @@ static erts_aint_t next_time_internal(void) /* PRE: tiw_lock taken by caller */ i = (i + 1) % TIW_SIZE; } while (i != tiw_pos); dt = do_time_read(); - return ((min >= dt) ? (min - dt) : 0); + if (min <= (Uint32) dt) + return 0; + if ((min - (Uint32) dt) > (Uint32) ERTS_SHORT_TIME_T_MAX) + return ERTS_SHORT_TIME_T_MAX; + return (erts_short_time_t) (min - (Uint32) dt); } static void remove_timer(ErlTimer *p) { @@ -191,9 +206,9 @@ static void remove_timer(ErlTimer *p) { } /* Private export to erl_time_sup.c */ -erts_aint_t erts_next_time(void) +erts_short_time_t erts_next_time(void) { - erts_aint_t ret; + erts_short_time_t ret; erts_smp_mtx_lock(&tiw_lock); (void)do_time_update(); @@ -202,7 +217,7 @@ erts_aint_t erts_next_time(void) return ret; } -static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is write-locked */ +static ERTS_INLINE void bump_timer_internal(erts_short_time_t dt) /* PRE: tiw_lock is write-locked */ { Uint keep_pos; Uint count; @@ -273,7 +288,7 @@ static ERTS_INLINE void bump_timer_internal(erts_aint_t dt) /* PRE: tiw_lock is } } -void erts_bump_timer(erts_aint_t dt) /* dt is value from do_time */ +void erts_bump_timer(erts_short_time_t dt) /* dt is value from do_time */ { erts_smp_mtx_lock(&tiw_lock); bump_timer_internal(dt); @@ -378,8 +393,8 @@ erts_set_timer(ErlTimer* p, ErlTimeoutProc timeout, ErlCancelProc cancel, insert_timer(p, t); erts_smp_mtx_unlock(&tiw_lock); #if defined(ERTS_SMP) - if (t <= (Uint) LONG_MAX) - erts_sys_schedule_interrupt_timed(1, (long) t); + if (t <= (Uint) ERTS_SHORT_TIME_T_MAX) + erts_sys_schedule_interrupt_timed(1, (erts_short_time_t) t); #endif } @@ -419,7 +434,7 @@ Uint erts_time_left(ErlTimer *p) { Uint left; - erts_aint_t dt; + erts_short_time_t dt; erts_smp_mtx_lock(&tiw_lock); diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c index df03f5e42c..4105f194a9 100644 --- a/erts/emulator/beam/utils.c +++ b/erts/emulator/beam/utils.c @@ -2661,6 +2661,7 @@ tailrecur_ne: #endif #define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2)) #define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1)) +#define BIG_ARITY_FLOAT_MAX (1024 / D_EXP) /* arity of max float as a bignum */ b_tag = tag_val_def(bw); switch(_NUMBER_CODE(a_tag, b_tag)) { @@ -2693,16 +2694,24 @@ tailrecur_ne: } #endif // ERTS_SIZEOF_ETERM == 8 break; + case FLOAT_BIG: + { + Wterm tmp = aw; + aw = bw; + bw = tmp; + }/* fall through */ case BIG_FLOAT: GET_DOUBLE(bw, f2); if ((f2.fd < (double) (MAX_SMALL + 1)) && (f2.fd > (double) (MIN_SMALL - 1))) { // Float is a Sint j = big_sign(aw) ? -1 : 1; - } else if ((pow(2.0,(big_arity(aw)-1.0)*D_EXP)-1.0) > fabs(f2.fd)) { + } else if (big_arity(aw) > BIG_ARITY_FLOAT_MAX + || pow(2.0,(big_arity(aw)-1)*D_EXP) > fabs(f2.fd)) { // If bignum size shows that it is bigger than the abs float j = big_sign(aw) ? -1 : 1; - } else if ((pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) { + } else if (big_arity(aw) < BIG_ARITY_FLOAT_MAX + && (pow(2.0,(big_arity(aw))*D_EXP)-1.0) < fabs(f2.fd)) { // If bignum size shows that it is smaller than the abs float j = f2.fd < 0 ? 1 : -1; } else if (f2.fd < MAX_LOSSLESS_FLOAT && f2.fd > MIN_LOSSLESS_FLOAT) { @@ -2716,6 +2725,9 @@ tailrecur_ne: big = double_to_big(f2.fd, big_buf); j = big_comp(aw, big); } + if (_NUMBER_CODE(a_tag, b_tag) == FLOAT_BIG) { + j = -j; + } break; case FLOAT_SMALL: GET_DOUBLE(aw, f1); @@ -2740,29 +2752,6 @@ tailrecur_ne: } #endif // ERTS_SIZEOF_ETERM == 8 break; - case FLOAT_BIG: - GET_DOUBLE(aw, f1); - if ((f1.fd < (double) (MAX_SMALL + 1)) - && (f1.fd > (double) (MIN_SMALL - 1))) { // Float is a Sint - j = big_sign(bw) ? 1 : -1; - } else if ((pow(2.0, (big_arity(bw) - 1.0) * D_EXP) - 1.0) > fabs(f1.fd)) { - // If bignum size shows that it is bigger than the abs float - j = big_sign(bw) ? 1 : -1; - } else if ((pow(2.0,(big_arity(bw))*D_EXP)-1.0) < fabs(f1.fd)) { - // If bignum size shows that it is smaller than the abs float - j = f1.fd < 0 ? -1 : 1; - } else if (f1.fd < MAX_LOSSLESS_FLOAT && f1.fd > MIN_LOSSLESS_FLOAT) { - // Float is within the no loss limit - if (big_to_double(bw, &f2.fd) < 0) { - j = big_sign(bw) ? 1 : -1; - } else { - j = float_comp(f1.fd, f2.fd); - } - } else { - big = double_to_big(f1.fd, big_buf); - j = big_comp(big, bw); - } - break; default: j = b_tag - a_tag; } diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index e0d869f328..45089dcc2f 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -8729,8 +8729,15 @@ static int tcp_remain(tcp_descriptor* desc, int* len) else if (tlen == 0) { /* need unknown more */ *len = 0; if (nsz == 0) { - if (nfill == n) - goto error; + if (nfill == n) { + if (desc->inet.psize != 0 && desc->inet.psize > nfill) { + if (tcp_expand_buffer(desc, desc->inet.psize) < 0) + return -1; + return desc->inet.psize; + } + else + goto error; + } DEBUGF((" => restart more=%d\r\n", nfill - n)); return nfill - n; } diff --git a/erts/emulator/hipe/hipe_mode_switch.c b/erts/emulator/hipe/hipe_mode_switch.c index 4d75883fc5..6a3ce5608f 100644 --- a/erts/emulator/hipe/hipe_mode_switch.c +++ b/erts/emulator/hipe/hipe_mode_switch.c @@ -337,14 +337,22 @@ Process *hipe_mode_switch(Process *p, unsigned cmd, Eterm reg[]) * stack: to this end hipe_${ARCH}_glue.S stores the BIF's * arity in p->hipe.narity. * - * If the BIF emptied the stack (typically hibernate), p->hipe.nsp is - * NULL and there is no need to get rid of stacked parameters. + * If the BIF emptied the stack (typically hibernate), p->hipe.nstack + * is NULL and there is no need to get rid of stacked parameters. */ unsigned int i, is_recursive = 0; - if (p->hipe.nsp != NULL) { + if (p->hipe.nstack != NULL) { + ASSERT(p->hipe.nsp != NULL); is_recursive = hipe_trap_from_native_is_recursive(p); } + else { + /* Some architectures (risc) need this re-reset of nsp as the + * BIF wrapper do not detect stack change and causes an obsolete + * stack pointer to be saved in p->hipe.nsp before return to us. + */ + p->hipe.nsp = NULL; + } /* Schedule next process if current process was hibernated or is waiting for messages */ diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c index 2005450c36..23a4bf1b04 100644 --- a/erts/emulator/sys/common/erl_check_io.c +++ b/erts/emulator/sys/common/erl_check_io.c @@ -1134,7 +1134,8 @@ ERTS_CIO_EXPORT(erts_check_io_interrupt)(int set) } void -ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, long msec) +ERTS_CIO_EXPORT(erts_check_io_interrupt_timed)(int set, + erts_short_time_t msec) { ERTS_CIO_POLL_INTR_TMD(pollset.ps, set, msec); } diff --git a/erts/emulator/sys/common/erl_check_io.h b/erts/emulator/sys/common/erl_check_io.h index 7cc1658062..edab7947ba 100644 --- a/erts/emulator/sys/common/erl_check_io.h +++ b/erts/emulator/sys/common/erl_check_io.h @@ -46,8 +46,8 @@ void erts_check_io_async_sig_interrupt_nkp(void); #endif void erts_check_io_interrupt_kp(int); void erts_check_io_interrupt_nkp(int); -void erts_check_io_interrupt_timed_kp(int, long); -void erts_check_io_interrupt_timed_nkp(int, long); +void erts_check_io_interrupt_timed_kp(int, erts_short_time_t); +void erts_check_io_interrupt_timed_nkp(int, erts_short_time_t); void erts_check_io_kp(int); void erts_check_io_nkp(int); void erts_init_check_io_kp(void); @@ -64,7 +64,7 @@ int erts_check_io_max_files(void); void erts_check_io_async_sig_interrupt(void); #endif void erts_check_io_interrupt(int); -void erts_check_io_interrupt_timed(int, long); +void erts_check_io_interrupt_timed(int, erts_short_time_t); void erts_check_io(int); void erts_init_check_io(void); diff --git a/erts/emulator/sys/common/erl_poll.c b/erts/emulator/sys/common/erl_poll.c index 80db2055a2..b6cb271f17 100644 --- a/erts/emulator/sys/common/erl_poll.c +++ b/erts/emulator/sys/common/erl_poll.c @@ -2171,7 +2171,7 @@ ERTS_POLL_EXPORT(erts_poll_async_sig_interrupt)(ErtsPollSet ps) void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet ps, int set, - long msec) + erts_short_time_t msec) { #if ERTS_POLL_ASYNC_INTERRUPT_SUPPORT || defined(ERTS_SMP) if (!set) diff --git a/erts/emulator/sys/common/erl_poll.h b/erts/emulator/sys/common/erl_poll.h index e0296c6a33..8dde619105 100644 --- a/erts/emulator/sys/common/erl_poll.h +++ b/erts/emulator/sys/common/erl_poll.h @@ -223,7 +223,7 @@ void ERTS_POLL_EXPORT(erts_poll_interrupt)(ErtsPollSet, int); void ERTS_POLL_EXPORT(erts_poll_interrupt_timed)(ErtsPollSet, int, - long); + erts_short_time_t); ErtsPollEvents ERTS_POLL_EXPORT(erts_poll_control)(ErtsPollSet, ErtsSysFdType, ErtsPollEvents, diff --git a/erts/emulator/sys/unix/erl_unix_sys.h b/erts/emulator/sys/unix/erl_unix_sys.h index 9a5ed9f5bc..c8fcec8547 100644 --- a/erts/emulator/sys/unix/erl_unix_sys.h +++ b/erts/emulator/sys/unix/erl_unix_sys.h @@ -146,6 +146,7 @@ typedef void *GETENV_STATE; /* ** For the erl_timer_sup module. */ +typedef time_t erts_time_t; typedef struct timeval SysTimeval; diff --git a/erts/emulator/sys/unix/sys.c b/erts/emulator/sys/unix/sys.c index c6b63350e5..52477467b3 100644 --- a/erts/emulator/sys/unix/sys.c +++ b/erts/emulator/sys/unix/sys.c @@ -265,7 +265,7 @@ struct { int (*event)(ErlDrvPort, ErlDrvEvent, ErlDrvEventData); void (*check_io_as_interrupt)(void); void (*check_io_interrupt)(int); - void (*check_io_interrupt_tmd)(int, long); + void (*check_io_interrupt_tmd)(int, erts_short_time_t); void (*check_io)(int); Uint (*size)(void); Eterm (*info)(void *); @@ -371,7 +371,7 @@ erts_sys_schedule_interrupt(int set) #ifdef ERTS_SMP void -erts_sys_schedule_interrupt_timed(int set, long msec) +erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec) { ERTS_CHK_IO_INTR_TMD(set, msec); } diff --git a/erts/emulator/sys/vxworks/erl_vxworks_sys.h b/erts/emulator/sys/vxworks/erl_vxworks_sys.h index ae46403600..69d9ca3478 100644 --- a/erts/emulator/sys/vxworks/erl_vxworks_sys.h +++ b/erts/emulator/sys/vxworks/erl_vxworks_sys.h @@ -158,6 +158,7 @@ typedef struct _vxworks_tms { typedef long long SysHrTime; +typedef time_t erts_time_t; typedef struct timeval SysTimeval; extern int sys_init_hrtime(void); diff --git a/erts/emulator/sys/win32/erl_poll.c b/erts/emulator/sys/win32/erl_poll.c index ab4ef05118..7a1d129cd5 100644 --- a/erts/emulator/sys/win32/erl_poll.c +++ b/erts/emulator/sys/win32/erl_poll.c @@ -442,8 +442,8 @@ poll_wait_timeout(ErtsPollSet ps, SysTimeval *tvp) if (erts_atomic32_read_nob(&ps->wakeup_state) != ERTS_POLL_NOT_WOKEN) return (DWORD) 0; - if (timeout > ERTS_AINT32_T_MAX) /* Also prevents DWORD overflow */ - timeout = ERTS_AINT32_T_MAX; + if (timeout > ((time_t) ERTS_AINT32_T_MAX)) + timeout = ERTS_AINT32_T_MAX; /* Also prevents DWORD overflow */ erts_smp_atomic32_set_relb(&ps->timeout, (erts_aint32_t) timeout); return (DWORD) timeout; @@ -1012,7 +1012,7 @@ void erts_poll_interrupt(ErtsPollSet ps, int set /* bool */) void erts_poll_interrupt_timed(ErtsPollSet ps, int set /* bool */, - long msec) + erts_short_time_t msec) { HARDTRACEF(("In erts_poll_interrupt_timed(%d,%ld)",set,msec)); if (!set) diff --git a/erts/emulator/sys/win32/erl_win_sys.h b/erts/emulator/sys/win32/erl_win_sys.h index ac5639b701..e8453205ea 100644 --- a/erts/emulator/sys/win32/erl_win_sys.h +++ b/erts/emulator/sys/win32/erl_win_sys.h @@ -117,6 +117,17 @@ int erts_check_io_debug(void); #define SYS_CLK_TCK 1000 #define SYS_CLOCK_RESOLUTION 1 +#if SIZEOF_TIME_T != 8 +# error "Unexpected sizeof(time_t)" +#endif + +/* + * gcc uses a 4 byte time_t and vc++ uses an 8 byte time_t. + * Types seen in beam_emu.c *need* to have the same size + * as in the rest of the system... + */ +typedef __int64 erts_time_t; + struct tm *sys_localtime_r(time_t *epochs, struct tm *ptm); struct tm *sys_gmtime_r(time_t *epochs, struct tm *ptm); time_t sys_mktime( struct tm *ptm); @@ -128,8 +139,8 @@ time_t sys_mktime( struct tm *ptm); #define mktime sys_mktime typedef struct { - long tv_sec; - long tv_usec; + erts_time_t tv_sec; + erts_time_t tv_usec; } SysTimeval; typedef struct { diff --git a/erts/emulator/sys/win32/sys.c b/erts/emulator/sys/win32/sys.c index a49fa8ca34..a701747b78 100755 --- a/erts/emulator/sys/win32/sys.c +++ b/erts/emulator/sys/win32/sys.c @@ -3290,7 +3290,7 @@ erts_sys_schedule_interrupt(int set) #ifdef ERTS_SMP void -erts_sys_schedule_interrupt_timed(int set, long msec) +erts_sys_schedule_interrupt_timed(int set, erts_short_time_t msec) { erts_check_io_interrupt_timed(set, msec); } diff --git a/erts/emulator/test/code_SUITE.erl b/erts/emulator/test/code_SUITE.erl index 2f9b01cc92..25ce94096f 100644 --- a/erts/emulator/test/code_SUITE.erl +++ b/erts/emulator/test/code_SUITE.erl @@ -20,7 +20,7 @@ -module(code_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, - new_binary_types/1, + versions/1,new_binary_types/1, t_check_process_code/1,t_check_old_code/1, t_check_process_code_ets/1, external_fun/1,get_chunk/1,module_md5/1,make_stub/1, @@ -33,7 +33,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [new_binary_types, t_check_process_code, + [versions, new_binary_types, t_check_process_code, t_check_process_code_ets, t_check_old_code, external_fun, get_chunk, module_md5, make_stub, make_stub_many_funs, constant_pools, constant_refc_binaries, false_dependency, @@ -56,6 +56,60 @@ init_per_group(_GroupName, Config) -> end_per_group(_GroupName, Config) -> Config. +%% Make sure that only two versions of a module can be loaded. +versions(Config) when is_list(Config) -> + V1 = compile_version(1, Config), + V2 = compile_version(2, Config), + V3 = compile_version(3, Config), + + {ok,P1,1} = load_version(V1, 1), + {ok,P2,2} = load_version(V2, 2), + {error,not_purged} = load_version(V2, 2), + {error,not_purged} = load_version(V3, 3), + + 1 = check_version(P1), + 2 = check_version(P2), + 2 = versions:version(), + + %% Kill processes, unload code. + P1 ! P2 ! done, + _ = monitor(process, P1), + _ = monitor(process, P2), + receive + {'DOWN',_,process,P1,normal} -> ok + end, + receive + {'DOWN',_,process,P2,normal} -> ok + end, + true = erlang:purge_module(versions), + true = erlang:delete_module(versions), + true = erlang:purge_module(versions), + ok. + +compile_version(Version, Config) -> + Data = ?config(data_dir, Config), + File = filename:join(Data, "versions"), + {ok,versions,Bin} = compile:file(File, [{d,'VERSION',Version}, + binary,report]), + Bin. + +load_version(Code, Ver) -> + case erlang:load_module(versions, Code) of + {module,versions} -> + Pid = spawn_link(versions, loop, []), + Ver = versions:version(), + Ver = check_version(Pid), + {ok,Pid,Ver}; + Error -> + Error + end. + +check_version(Pid) -> + Pid ! {self(),version}, + receive + {Pid,version,Version} -> + Version + end. new_binary_types(Config) when is_list(Config) -> ?line Data = ?config(data_dir, Config), diff --git a/erts/emulator/test/code_SUITE_data/versions.erl b/erts/emulator/test/code_SUITE_data/versions.erl new file mode 100644 index 0000000000..7a6fd8847d --- /dev/null +++ b/erts/emulator/test/code_SUITE_data/versions.erl @@ -0,0 +1,33 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(versions). +-export([loop/0,version/0]). + +loop() -> + receive + {Pid,version} -> + Pid ! {self(),version,version()}, + loop(); + done -> + ok + end. + +version() -> + ?VERSION. diff --git a/erts/emulator/test/decode_packet_SUITE.erl b/erts/emulator/test/decode_packet_SUITE.erl index c0499554eb..4acbe8c6e0 100644 --- a/erts/emulator/test/decode_packet_SUITE.erl +++ b/erts/emulator/test/decode_packet_SUITE.erl @@ -26,12 +26,14 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, - basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1]). + basic/1, packet_size/1, neg/1, http/1, line/1, ssl/1, otp_8536/1, + otp_9389/1, otp_9389_line/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [basic, packet_size, neg, http, line, ssl, otp_8536]. + [basic, packet_size, neg, http, line, ssl, otp_8536, + otp_9389, otp_9389_line]. groups() -> []. @@ -251,6 +253,28 @@ packet_size(Config) when is_list(Config) -> ?line {error,_} = decode_pkt(4,<<Size:32,Packet/binary>>) end, lists:seq(-10,-1)), + + %% Test OTP-9389, long HTTP header lines. + Opts = [{packet_size, 128}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 64), "\r\n\r\n"]), + <<Pkt1:50/binary, Pkt2/binary>> = Pkt, + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + ?line {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + ?line {ok, {http_header,_,"Link",_,_}, _} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + + Pkt3 = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($Y, 129), "\r\n\r\n"]), + ?line {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest3} = + erlang:decode_packet(http, Pkt3, Opts), + ?line {ok, {http_header,_,'Host',_,"localhost"}, Rest4} = + erlang:decode_packet(httph, Rest3, Opts), + ?line {error, invalid} = erlang:decode_packet(httph, Rest4, Opts), + ok. @@ -557,3 +581,35 @@ decode_pkt(Type,Bin,Opts) -> %%io:format(" -> ~p\n",[Res]), Res. +otp_9389(doc) -> ["Verify line_length works correctly for HTTP headers"]; +otp_9389(suite) -> []; +otp_9389(Config) when is_list(Config) -> + Opts = [{packet_size, 16384}, {line_length, 3000}], + Pkt = list_to_binary(["GET / HTTP/1.1\r\nHost: localhost\r\nLink: /", + string:chars($X, 8192), + "\r\nContent-Length: 0\r\n\r\n"]), + <<Pkt1:5000/binary, Pkt2/binary>> = Pkt, + {ok, {http_request,'GET',{abs_path,"/"},{1,1}}, Rest1} = + erlang:decode_packet(http, Pkt1, Opts), + {ok, {http_header,_,'Host',_,"localhost"}, Rest2} = + erlang:decode_packet(httph, Rest1, Opts), + {more, undefined} = erlang:decode_packet(httph, Rest2, Opts), + {ok, {http_header,_,"Link",_,Link}, Rest3} = + erlang:decode_packet(httph, list_to_binary([Rest2, Pkt2]), Opts), + true = (length(Link) > 8000), + {ok, {http_header,_,'Content-Length',_,"0"}, <<"\r\n">>} = + erlang:decode_packet(httph, Rest3, Opts), + ok. + +otp_9389_line(doc) -> ["Verify packet_size works correctly for line mode"]; +otp_9389_line(suite) -> []; +otp_9389_line(Config) when is_list(Config) -> + Opts = [{packet_size, 20}], + Line1 = <<"0123456789012345678\n">>, + Line2 = <<"0123456789\n">>, + Line3 = <<"01234567890123456789\n">>, + Pkt = list_to_binary([Line1, Line2, Line3]), + ?line {ok, Line1, Rest1} = erlang:decode_packet(line, Pkt, Opts), + ?line {ok, Line2, Rest2} = erlang:decode_packet(line, Rest1, Opts), + ?line {error, invalid} = erlang:decode_packet(line, Rest2, Opts), + ok. diff --git a/erts/emulator/test/driver_SUITE.erl b/erts/emulator/test/driver_SUITE.erl index c07dbc5871..e159c37d2c 100644 --- a/erts/emulator/test/driver_SUITE.erl +++ b/erts/emulator/test/driver_SUITE.erl @@ -1796,7 +1796,7 @@ driver_select_use0(Config) -> thread_mseg_alloc_cache_clean(Config) when is_list(Config) -> case {erlang:system_info(threads), - mseg_inst_info(0), + erlang:system_info({allocator,mseg_alloc}), driver_alloc_sbct()} of {_, false, _} -> ?line {skipped, "No mseg_alloc"}; diff --git a/erts/emulator/test/mtx_SUITE.erl b/erts/emulator/test/mtx_SUITE.erl index 879d2f61dd..024c3456a8 100644 --- a/erts/emulator/test/mtx_SUITE.erl +++ b/erts/emulator/test/mtx_SUITE.erl @@ -122,7 +122,7 @@ long_rwlock(Config) when is_list(Config) -> %% A very short run time is expected, since %% threads in the test mostly wait ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 100, + ?line true = RunTime < 400, ?line RunTimeStr = "Run-time during test was "++integer_to_list(RunTime)++" ms.", case LLRes of ok -> @@ -281,7 +281,7 @@ hammer_sched_rwlock_test(FreqRead, LockCheck, Blocking, WaitLocked, WaitUnlocked _ -> {_, RunTime} = statistics(runtime), ?t:format("RunTime=~p~n", [RunTime]), - ?line true = RunTime < 500, + ?line true = RunTime < 700, {comment, "Run-time during test was " ++ integer_to_list(RunTime) diff --git a/erts/emulator/test/scheduler_SUITE.erl b/erts/emulator/test/scheduler_SUITE.erl index debb54579b..8931562828 100644 --- a/erts/emulator/test/scheduler_SUITE.erl +++ b/erts/emulator/test/scheduler_SUITE.erl @@ -55,7 +55,7 @@ scheduler_suspend/1, reader_groups/1]). --define(DEFAULT_TIMEOUT, ?t:minutes(10)). +-define(DEFAULT_TIMEOUT, ?t:minutes(15)). -define(MIN_SCHEDULER_TEST_TIMEOUT, ?t:minutes(1)). @@ -519,16 +519,18 @@ bound_loop(NS, N, M, Sched) -> bindings(Node, BindType) -> Parent = self(), Ref = make_ref(), - spawn_link(Node, - fun () -> - enable_internal_state(), - Res = (catch erts_debug:get_internal_state( - {fake_scheduler_bindings, BindType})), - Parent ! {Ref, Res} - end), + Pid = spawn_link(Node, + fun () -> + enable_internal_state(), + Res = (catch erts_debug:get_internal_state( + {fake_scheduler_bindings, + BindType})), + Parent ! {Ref, Res} + end), receive {Ref, Res} -> ?t:format("~p: ~p~n", [BindType, Res]), + unlink(Pid), Res end. @@ -1684,7 +1686,7 @@ do_it(Tracer, Low, Normal, High, Max, RedsPerSchedLimit) -> EndWait = now(), BalanceWait = timer:now_diff(EndWait,StartWait) div 1000, erlang:display({balance_wait, BalanceWait}), - Timeout = ?DEFAULT_TIMEOUT - ?t:seconds(10) - BalanceWait, + Timeout = ?DEFAULT_TIMEOUT - ?t:minutes(4) - BalanceWait, Res = case Timeout < ?MIN_SCHEDULER_TEST_TIMEOUT of true -> stop_work(Low, Normal, High, Max), diff --git a/erts/emulator/test/sensitive_SUITE.erl b/erts/emulator/test/sensitive_SUITE.erl index 634df367ca..e073eab596 100644 --- a/erts/emulator/test/sensitive_SUITE.erl +++ b/erts/emulator/test/sensitive_SUITE.erl @@ -160,8 +160,7 @@ recv_trace(Config) when is_list(Config) -> ?line {messages,Messages} = process_info(Tracer, messages), [{trace,Parent,'receive',a}, {trace,Parent,'receive',{trace_delivered,_,_}}, - {trace,Parent,'receive',c}, - {trace,Parent,'receive',{trace_delivered,_,_}}] = Messages, + {trace,Parent,'receive',c}|_] = Messages, ?line unlink(Tracer), exit(Tracer, kill), ?line unlink(Sender), exit(Sender, kill), |