Mail archive
alpine-aports

[alpine-aports] [PATCH] testing/erlang: Update to 18.0.2

From: Marlus Saraiva <marlus.saraiva_at_gmail.com>
Date: Wed, 15 Jul 2015 20:24:14 +0000

---
 .../erlang/0050-otp-update-version-18.0.2.patch    | 839 +++++++++++++++++++++
 testing/erlang/APKBUILD                            |  14 +-
 2 files changed, 848 insertions(+), 5 deletions(-)
 create mode 100644 testing/erlang/0050-otp-update-version-18.0.2.patch
diff --git a/testing/erlang/0050-otp-update-version-18.0.2.patch b/testing/erlang/0050-otp-update-version-18.0.2.patch
new file mode 100644
index 0000000..ccae0a6
--- /dev/null
+++ b/testing/erlang/0050-otp-update-version-18.0.2.patch
_at_@ -0,0 +1,839 @@
+--- a/HOWTO/INSTALL.md
++++ b/HOWTO/INSTALL.md
+_at_@ -400,6 +400,12 @@ Some of the available `configure` options are:
+ 	no automatic dependency handling between applications. If you disable
+ 	an application that another application depends on, you also have to disable the
+ 	dependant application.
++*   `--enable-gettimeofday-as-os-system-time` - Force usage of `gettimeofday()` for
++    OS system time.
++*   `--enable-prefer-elapsed-monotonic-time-during-suspend` - Prefer an OS monotonic
++    time source with elapsed time during suspend.
++*   `--disable-prefer-elapsed-monotonic-time-during-suspend` - Do not prefer an OS
++    monotonic time source with elapsed time during suspend.
+ *   `--enable-dirty-schedulers` - Enable the **experimental** dirty schedulers
+     functionality. Note that the dirty schedulers functionality is experimental,
+     and **not supported**. This functionality **will** be subject to backward
+--- a/OTP_VERSION
++++ b/OTP_VERSION
+_at_@ -1 +1 @@
+-18.0.1
++18.0.2
+--- a/erts/aclocal.m4
++++ b/erts/aclocal.m4
+_at_@ -726,9 +726,15 @@ esac
+ 
+ AC_DEFUN(ERL_MONOTONIC_CLOCK,
+ [
+-  default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_BOOTTIME CLOCK_MONOTONIC"
+-  low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST"
+-  high_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_PRECISE"
++  if test "$3" = "yes"; then
++     default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_BOOTTIME CLOCK_MONOTONIC"
++     low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST"
++     high_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_PRECISE"
++  else
++     default_resolution_clock_gettime_monotonic="CLOCK_HIGHRES CLOCK_UPTIME CLOCK_MONOTONIC"
++     low_resolution_clock_gettime_monotonic="CLOCK_MONOTONIC_COARSE CLOCK_UPTIME_FAST"
++     high_resolution_clock_gettime_monotonic="CLOCK_UPTIME_PRECISE"
++  fi
+ 
+   case "$1" in
+     high_resolution)
+_at_@ -1466,7 +1472,7 @@ AC_ARG_WITH(with_sparc_memory_order,
+ LM_CHECK_THR_LIB
+ ERL_INTERNAL_LIBS
+ 
+-ERL_MONOTONIC_CLOCK(high_resolution)
++ERL_MONOTONIC_CLOCK(high_resolution, undefined, no)
+ 
+ case $erl_monotonic_clock_func in
+   clock_gettime)
+_at_@ -2202,7 +2208,7 @@ AC_DEFUN(ERL_TIME_CORRECTION,
+ 
+ AC_ARG_WITH(clock-resolution,
+ AS_HELP_STRING([--with-clock-resolution=high|low|default],
+-               [specify wanted clock resolution)]))
++               [specify wanted clock resolution]))
+ 
+ AC_ARG_WITH(clock-gettime-realtime-id,
+ AS_HELP_STRING([--with-clock-gettime-realtime-id=CLOCKID],
+_at_@ -2212,6 +2218,24 @@ AC_ARG_WITH(clock-gettime-monotonic-id,
+ AS_HELP_STRING([--with-clock-gettime-monotonic-id=CLOCKID],
+                [specify clock id to use with clock_gettime() for monotonic time)]))
+ 
++AC_ARG_ENABLE(prefer-elapsed-monotonic-time-during-suspend,
++	      AS_HELP_STRING([--enable-prefer-elapsed-monotonic-time-during-suspend],
++                             [Prefer an OS monotonic time source with elapsed time during suspend])
++	      AS_HELP_STRING([--disable-prefer-elapsed-monotonic-time-during-suspend],
++                             [Do not prefer an OS monotonic time source with elapsed time during suspend]),
++[ case "$enableval" in
++    yes) prefer_elapsed_monotonic_time_during_suspend=yes ;;
++    *)  prefer_elapsed_monotonic_time_during_suspend=no ;;
++  esac ], prefer_elapsed_monotonic_time_during_suspend=no)
++
++AC_ARG_ENABLE(gettimeofday-as-os-system-time,
++	      AS_HELP_STRING([--enable-gettimeofday-as-os-system-time],
++                             [Force usage of gettimeofday() for OS system time]),
++[ case "$enableval" in
++    yes) force_gettimeofday_os_system_time=yes ;;
++    *)  force_gettimeofday_os_system_time=no ;;
++  esac ], force_gettimeofday_os_system_time=no)
++
+ case "$with_clock_resolution" in
+    ""|no|yes)
+      with_clock_resolution=default;;
+_at_@ -2222,6 +2246,17 @@ case "$with_clock_resolution" in
+      ;;
+ esac
+ 
++if test "$force_gettimeofday_os_system_time" = "yes"; then
++
++  AC_CHECK_FUNCS([gettimeofday])
++  if test "$ac_cv_func_gettimeofday" = "yes"; then
++    AC_DEFINE(OS_SYSTEM_TIME_GETTIMEOFDAY,  [1], [Define if you want to implement erts_os_system_time() using gettimeofday()])
++  else
++    AC_MSG_ERROR([No gettimeofday() available])
++  fi
++
++else # $force_gettimeofday_os_system_time != yes
++
+ case "$with_clock_gettime_realtime_id" in
+    ""|no)
+      with_clock_gettime_realtime_id=no
+_at_@ -2239,23 +2274,6 @@ case "$with_clock_gettime_realtime_id" in
+      ;;
+ esac
+ 
+-case "$with_clock_gettime_monotonic_id" in
+-   ""|no)
+-     with_clock_gettime_monotonic_id=no
+-     ;;
+-   CLOCK_*CPUTIME*)
+-     AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the cputime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
+-     ;;
+-   CLOCK_REALTIME*|CLOCK_TAI*)
+-     AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the realtime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
+-     ;;
+-   CLOCK_*)
+-     ;;
+-   *)
+-     AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_monotonic_id])
+-     ;;
+-esac
+-
+ case "$with_clock_resolution-$with_clock_gettime_realtime_id" in
+   high-no)
+ 	ERL_WALL_CLOCK(high_resolution);;
+_at_@ -2296,15 +2314,34 @@ if test "x$erl_wall_clock_id" != "x"; then
+     AC_DEFINE_UNQUOTED(WALL_CLOCK_ID, [$erl_wall_clock_id], [Define to wall clock id to use])
+ fi
+ 
++fi # $force_gettimeofday_os_system_time != yes
++
++case "$with_clock_gettime_monotonic_id" in
++   ""|no)
++     with_clock_gettime_monotonic_id=no
++     ;;
++   CLOCK_*CPUTIME*)
++     AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the cputime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
++     ;;
++   CLOCK_REALTIME*|CLOCK_TAI*)
++     AC_MSG_ERROR([Invalid clock_gettime() monotonic clock id: Refusing to use the realtime clock id $with_clock_gettime_monotonic_id as monotonic clock id])
++     ;;
++   CLOCK_*)
++     ;;
++   *)
++     AC_MSG_ERROR([Invalid clock_gettime() clock id: $with_clock_gettime_monotonic_id])
++     ;;
++esac
++
+ case "$with_clock_resolution-$with_clock_gettime_monotonic_id" in
+   high-no)
+-	ERL_MONOTONIC_CLOCK(high_resolution);;
++	ERL_MONOTONIC_CLOCK(high_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
+   low-no)
+-	ERL_MONOTONIC_CLOCK(low_resolution);;
++	ERL_MONOTONIC_CLOCK(low_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
+   default-no)
+-	ERL_MONOTONIC_CLOCK(default_resolution);;
++	ERL_MONOTONIC_CLOCK(default_resolution, undefined, $prefer_elapsed_monotonic_time_during_suspend);;
+   *)
+-	ERL_MONOTONIC_CLOCK(custom_resolution, $with_clock_gettime_monotonic_id);;
++	ERL_MONOTONIC_CLOCK(custom_resolution, $with_clock_gettime_monotonic_id, $prefer_elapsed_monotonic_time_during_suspend);;
+ esac
+ 
+ case "$erl_monotonic_clock_func-$erl_monotonic_clock_id-$with_clock_gettime_monotonic_id" in
+_at_@ -2352,7 +2389,7 @@ if test $erl_cv_clock_gettime_monotonic_raw = yes; then
+   AC_DEFINE(HAVE_CLOCK_GETTIME_MONOTONIC_RAW, [1], [Define if you have clock_gettime(CLOCK_MONOTONIC_RAW, _)])
+ fi
+ 
+-ERL_MONOTONIC_CLOCK(high_resolution)
++ERL_MONOTONIC_CLOCK(high_resolution, undefined, no)
+ 
+ case $$erl_monotonic_clock_low_resolution-$erl_monotonic_clock_func in
+   no-mach_clock_get_time)
+--- a/erts/doc/src/notes.xml
++++ b/erts/doc/src/notes.xml
+_at_@ -31,6 +31,82 @@
+   </header>
+   <p>This document describes the changes made to the ERTS application.</p>
+ 
++<section><title>Erts 7.0.2</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    A process could end up in an inconsistent half exited
++	    state in the runtime system without SMP support. This
++	    could occur if the processes was traced by a port that it
++	    also was linked to, and the port terminated abnormally
++	    while handling a trace message for the process.</p>
++          <p>
++	    This bug has always existed in the runtime system without
++	    SMP support, but never in the runtime system with SMP
++	    support.</p>
++          <p>
++	    Own Id: OTP-12889 Aux Id: seq12885 </p>
++        </item>
++        <item>
++          <p>
++	    Removed unnecessary copying of data when retrieving
++	    corrected Erlang monotonic time.</p>
++          <p>
++	    Own Id: OTP-12894</p>
++        </item>
++        <item>
++          <p>
++	    Changed default OS monotonic clock source chosen at build
++	    time. This in order to improve performance. The behavior
++	    will now on most systems be that (both OS and Erlang)
++	    monotonic time stops when the system is suspended.</p>
++          <p>
++	    If you prefer that monotonic time elapse during suspend
++	    of the machine, you can pass the command line argument
++	    <c>--enable-prefer-elapsed-monotonic-time-during-suspend</c>
++	    to <c>configure</c> when building Erlang/OTP. The
++	    configuration stage will try to find such a clock source,
++	    but might not be able to find it. Note that there might
++	    be a performance penalty associated with such a clock
++	    source.</p>
++          <p>
++	    *** POTENTIAL INCOMPATIBILITY ***</p>
++          <p>
++	    Own Id: OTP-12895</p>
++        </item>
++        <item>
++          <p>
++	    <c>erlang:system_info(end_time)</c> returned a faulty
++	    value on 32-bit architectures.</p>
++          <p>
++	    Own Id: OTP-12896</p>
++        </item>
++      </list>
++    </section>
++
++
++    <section><title>Improvements and New Features</title>
++      <list>
++        <item>
++          <p>
++	    The <c>configure</c> command line argument
++	    <c>--enable-gettimeofday-as-os-system-time</c> has been
++	    added which force usage of <c>gettimeofday()</c> for OS
++	    system time. This will improve performance of
++	    <c>os:system_time()</c> and <c>os:timestamp()</c> on
++	    MacOS X, at the expense of worse accuracy, resolution and
++	    precision of Erlang monotonic time, Erlang system time,
++	    and OS system time.</p>
++          <p>
++	    Own Id: OTP-12892</p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>Erts 7.0.1</title>
+ 
+     <section><title>Fixed Bugs and Malfunctions</title>
+--- a/erts/emulator/beam/beam_emu.c
++++ b/erts/emulator/beam/beam_emu.c
+_at_@ -2163,6 +2163,22 @@ void process_main(void)
+ 	 OpCase(wait_f):
+ 
+ 	 wait2: {
++#ifndef ERTS_SMP
++	     if (ERTS_PROC_IS_EXITING(c_p)) {
++		 /*
++		  * I non smp case:
++		  *
++		  * Currently executing process might be sent an exit
++		  * signal if it is traced by a port that it also is
++		  * linked to, and the port terminates during the
++		  * trace. In this case we do *not* want to clear
++		  * the active flag, which will make the process hang
++		  * in limbo forever.
++		  */
++		 SWAPOUT;
++		 goto do_schedule;
++	     }
++#endif
+ 	     c_p->i = (BeamInstr *) Arg(0); /* L1 */
+ 	     SWAPOUT;
+ 	     c_p->arity = 0;
+_at_@ -6219,6 +6235,23 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re
+     int arity;
+     Eterm tmp;
+ 
++#ifndef ERTS_SMP
++    if (ERTS_PROC_IS_EXITING(c_p)) {
++	/*
++	 * I non smp case:
++	 *
++	 * Currently executing process might be sent an exit
++	 * signal if it is traced by a port that it also is
++	 * linked to, and the port terminates during the
++	 * trace. In this case we do *not* want to clear
++	 * the active flag, which will make the process hang
++	 * in limbo forever. Get out of here and terminate
++	 * the process...
++	 */
++	return -1;
++    }
++#endif
++
+     if (is_not_atom(module) || is_not_atom(function)) {
+ 	/*
+ 	 * No need to test args here -- done below.
+_at_@ -6295,7 +6328,16 @@ erts_hibernate(Process* c_p, Eterm module, Eterm function, Eterm args, Eterm* re
+ 	ERTS_VERIFY_UNUSED_TEMP_ALLOC(c_p);
+ 	PROCESS_MAIN_CHK_LOCKS(c_p);
+ 	erts_smp_proc_lock(c_p, ERTS_PROC_LOCK_MSGQ|ERTS_PROC_LOCK_STATUS);
+-#ifdef ERTS_SMP
++#ifndef ERTS_SMP
++	if (ERTS_PROC_IS_EXITING(c_p)) {
++	    /*
++	     * See comment in the begining of the function...
++	     *
++	     * This second test is needed since gc might be traced.
++	     */
++	    return -1;
++	}
++#else /* ERTS_SMP */
+ 	ERTS_SMP_MSGQ_MV_INQ2PRIVQ(c_p);
+ 	if (!c_p->msg.len)
+ #endif
+--- a/erts/emulator/beam/erl_process.c
++++ b/erts/emulator/beam/erl_process.c
+_at_@ -11409,6 +11409,22 @@ set_proc_exiting(Process *p,
+     KILL_CATCHES(p);
+     p->i = (BeamInstr *) beam_exit;
+ 
++#ifndef ERTS_SMP
++    if (state & (ERTS_PSFLG_RUNNING|ERTS_PSFLG_RUNNING_SYS)) {
++	/*
++	 * I non smp case:
++	 *
++	 * Currently executing process might be sent an exit
++	 * signal if it is traced by a port that it also is
++	 * linked to, and the port terminates during the
++	 * trace. In this case we want schedule out the
++	 * process as quickly as possible in order to detect
++	 * the event as fast as possible.
++	 */
++	ERTS_VBUMP_ALL_REDS(p);
++    }
++#endif
++
+     if (enqueue)
+ 	add2runq(enqueue > 0 ? p : make_proxy_proc(NULL, p, enq_prio),
+ 		 state,
+--- a/erts/emulator/beam/erl_time.h
++++ b/erts/emulator/beam/erl_time.h
+_at_@ -345,8 +345,10 @@ erts_time_unit_conversion(Uint64 value,
+ #endif /* !ERTS_COMPILE_TIME_MONOTONIC_TIME_UNIT */
+ 
+ #define ERTS_MONOTONIC_TIME_END_EXTERNAL				\
+-    (ERTS_MONOTONIC_TIME_START_EXTERNAL					\
+-     + (ERTS_MONOTONIC_END - ERTS_MONOTONIC_BEGIN))
++    (ERTS_MONOTONIC_TIME_START_EXTERNAL < 0				\
++     ? (ERTS_MONOTONIC_TIME_START_EXTERNAL				\
++	+ (ERTS_MONOTONIC_END - ERTS_MONOTONIC_BEGIN))			\
++     : (ERTS_MONOTONIC_END - ERTS_MONOTONIC_TIME_START_EXTERNAL))
+ 
+ #define ERTS_MSEC_TO_CLKTCKS__(MON) \
+     ((MON) * (ERTS_CLKTCK_RESOLUTION/1000))
+--- a/erts/emulator/beam/erl_time_sup.c
++++ b/erts/emulator/beam/erl_time_sup.c
+_at_@ -124,7 +124,11 @@ typedef struct {
+ 
+ typedef struct {
+     ErtsMonotonicCorrectionInstance prev;
+-    ErtsMonotonicCorrectionInstance curr;    
++    ErtsMonotonicCorrectionInstance curr;
++} ErtsMonotonicCorrectionInstances;
++
++typedef struct {
++    ErtsMonotonicCorrectionInstances insts;
+     ErtsMonotonicDriftData drift;
+     ErtsMonotonicTime last_check;
+     int short_check_interval;
+_at_@ -272,27 +276,24 @@ static ERTS_INLINE ErtsMonotonicTime
+ read_corrected_time(int os_drift_corrected)
+ {
+     ErtsMonotonicTime os_mtime;
+-    ErtsMonotonicCorrectionData cdata;
+-    ErtsMonotonicCorrectionInstance *cip;
++    ErtsMonotonicCorrectionInstance ci;
+ 
+     erts_smp_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx);
+ 
+     os_mtime = erts_os_monotonic_time();
+ 
+-    cdata = time_sup.inf.c.parmon.cdata;
+-
+-    erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx);
+-
+-    if (os_mtime >= cdata.curr.os_mtime)
+-	cip = &cdata.curr;
++    if (os_mtime >= time_sup.inf.c.parmon.cdata.insts.curr.os_mtime)
++	ci = time_sup.inf.c.parmon.cdata.insts.curr;
+     else {
+-	if (os_mtime < cdata.prev.os_mtime)
++	if (os_mtime < time_sup.inf.c.parmon.cdata.insts.prev.os_mtime)
+ 	    erl_exit(ERTS_ABORT_EXIT,
+ 		     "OS monotonic time stepped backwards\n");
+-	cip = &cdata.prev;
++	ci = time_sup.inf.c.parmon.cdata.insts.prev;
+     }
+ 
+-    return calc_corrected_erl_mtime(os_mtime, cip, NULL,
++    erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx);
++
++    return calc_corrected_erl_mtime(os_mtime, &ci, NULL,
+ 				    os_drift_corrected);
+ }
+ 
+_at_@ -360,9 +361,8 @@ check_time_correction(void *vesdp)
+ {
+     int init_drift_adj = !vesdp;
+     ErtsSchedulerData *esdp = (ErtsSchedulerData *) vesdp;
+-    ErtsMonotonicCorrectionData cdata;
+     ErtsMonotonicCorrection new_correction;
+-    ErtsMonotonicCorrectionInstance *cip;
++    ErtsMonotonicCorrectionInstance ci;
+     ErtsMonotonicTime mdiff, sdiff, os_mtime, erl_mtime, os_stime,
+ 	erl_stime, time_offset, timeout_pos;
+     Uint timeout;
+_at_@ -373,16 +373,15 @@ check_time_correction(void *vesdp)
+ 
+     erts_os_times(&os_mtime, &os_stime);
+ 
+-    cdata = time_sup.inf.c.parmon.cdata;
++    ci = time_sup.inf.c.parmon.cdata.insts.curr;
+ 
+     erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx);
+ 
+-    if (os_mtime < cdata.curr.os_mtime)
++    if (os_mtime < ci.os_mtime)
+ 	erl_exit(ERTS_ABORT_EXIT,
+ 		 "OS monotonic time stepped backwards\n");
+-    cip = &cdata.curr;
+ 
+-    erl_mtime = calc_corrected_erl_mtime(os_mtime, cip, &mdiff,
++    erl_mtime = calc_corrected_erl_mtime(os_mtime, &ci, &mdiff,
+ 					 os_drift_corrected);
+     time_offset = get_time_offset();
+     erl_stime = erl_mtime + time_offset;
+_at_@ -397,7 +396,7 @@ check_time_correction(void *vesdp)
+ 	    time_sup.inf.c.shadow_offset = 0;
+     }
+ 
+-    new_correction = cip->correction;
++    new_correction = ci.correction;
+ 
+     if (time_sup.r.o.warp_mode == ERTS_MULTI_TIME_WARP_MODE
+ 	&& (sdiff < -2*time_sup.r.o.adj.small_diff
+_at_@ -408,7 +407,7 @@ check_time_correction(void *vesdp)
+ 	set_time_offset(time_offset);
+ 	schedule_send_time_offset_changed_notifications(time_offset);
+ 	begin_short_intervals = 1;
+-	if (cdata.curr.correction.error != 0) {
++	if (ci.correction.error != 0) {
+ 	    set_new_correction = 1;
+ 	    new_correction.error = 0;
+ 	}
+_at_@ -425,12 +424,12 @@ check_time_correction(void *vesdp)
+ 	time_sup.inf.c.shadow_offset -= sdiff;
+ 	sdiff = 0;
+ 	begin_short_intervals = 1;
+-	if (cdata.curr.correction.error != 0) {
++	if (ci.correction.error != 0) {
+ 	    set_new_correction = 1;
+ 	    new_correction.error = 0;
+ 	}
+     }
+-    else if (cdata.curr.correction.error == 0) {
++    else if (ci.correction.error == 0) {
+ 	if (sdiff < -time_sup.r.o.adj.small_diff) {
+ 	    set_new_correction = 1;
+ 	    if (sdiff < -time_sup.r.o.adj.large_diff)
+_at_@ -446,9 +445,9 @@ check_time_correction(void *vesdp)
+ 		new_correction.error = -ERTS_TCORR_ERR_SMALL_ADJ;
+ 	}
+     }
+-    else if (cdata.curr.correction.error > 0) {
++    else if (ci.correction.error > 0) {
+ 	if (sdiff < 0) {
+-	    if (cdata.curr.correction.error != ERTS_TCORR_ERR_LARGE_ADJ
++	    if (ci.correction.error != ERTS_TCORR_ERR_LARGE_ADJ
+ 		&& sdiff < -time_sup.r.o.adj.large_diff) {
+ 		new_correction.error = ERTS_TCORR_ERR_LARGE_ADJ;
+ 		set_new_correction = 1;
+_at_@ -466,9 +465,9 @@ check_time_correction(void *vesdp)
+ 	    new_correction.error = 0;
+ 	}
+     }
+-    else /* if (cdata.curr.correction.error < 0) */ { 
++    else /* if (ci.correction.error < 0) */ { 
+ 	if (0 < sdiff) {
+-	    if (cdata.curr.correction.error != -ERTS_TCORR_ERR_LARGE_ADJ
++	    if (ci.correction.error != -ERTS_TCORR_ERR_LARGE_ADJ
+ 		&& time_sup.r.o.adj.large_diff < sdiff) {
+ 		new_correction.error = -ERTS_TCORR_ERR_LARGE_ADJ;
+ 		set_new_correction = 1;
+_at_@ -631,8 +630,8 @@ check_time_correction(void *vesdp)
+ #ifdef ERTS_TIME_CORRECTION_PRINT
+     print_correction(set_new_correction,
+ 		     sdiff,
+-		     cip->correction.error,
+-		     cip->correction.drift,
++		     ci.correction.error,
++		     ci.correction.drift,
+ 		     new_correction.error,
+ 		     new_correction.drift,
+ 		     timeout);
+_at_@ -644,7 +643,7 @@ check_time_correction(void *vesdp)
+ 	os_mtime = erts_os_monotonic_time();
+ 
+ 	/* Save previous correction instance */
+-	time_sup.inf.c.parmon.cdata.prev = *cip;
++	time_sup.inf.c.parmon.cdata.insts.prev = ci;
+ 
+ 	/*
+ 	 * Current correction instance begin when
+_at_@ -657,15 +656,15 @@ check_time_correction(void *vesdp)
+ 	 * next OS monotonic time using previous
+ 	 * correction.
+ 	 */
+-	erl_mtime = calc_corrected_erl_mtime(os_mtime, cip, NULL,
++	erl_mtime = calc_corrected_erl_mtime(os_mtime, &ci, NULL,
+ 					     os_drift_corrected);
+ 
+ 	/*
+ 	 * Save new current correction instance.
+ 	 */
+-	time_sup.inf.c.parmon.cdata.curr.erl_mtime = erl_mtime;
+-	time_sup.inf.c.parmon.cdata.curr.os_mtime = os_mtime;
+-	time_sup.inf.c.parmon.cdata.curr.correction = new_correction;
++	time_sup.inf.c.parmon.cdata.insts.curr.erl_mtime = erl_mtime;
++	time_sup.inf.c.parmon.cdata.insts.curr.os_mtime = os_mtime;
++	time_sup.inf.c.parmon.cdata.insts.curr.correction = new_correction;
+ 
+ 	erts_smp_rwmtx_rwunlock(&time_sup.inf.c.parmon.rwmtx);
+     }
+_at_@ -784,24 +783,22 @@ static ErtsMonotonicTime
+ finalize_corrected_time_offset(ErtsSystemTime *stimep)
+ {
+     ErtsMonotonicTime os_mtime;
+-    ErtsMonotonicCorrectionData cdata;
+-    ErtsMonotonicCorrectionInstance *cip;
++    ErtsMonotonicCorrectionInstance ci;
+     int os_drift_corrected = time_sup.r.o.os_corrected_monotonic_time;
+ 
+     erts_smp_rwmtx_rlock(&time_sup.inf.c.parmon.rwmtx);
+ 
+     erts_os_times(&os_mtime, stimep);
+ 
+-    cdata = time_sup.inf.c.parmon.cdata;
++    ci = time_sup.inf.c.parmon.cdata.insts.curr;
+ 
+     erts_smp_rwmtx_runlock(&time_sup.inf.c.parmon.rwmtx);
+ 
+-    if (os_mtime < cdata.curr.os_mtime)
++    if (os_mtime < ci.os_mtime)
+ 	erl_exit(ERTS_ABORT_EXIT,
+ 		 "OS monotonic time stepped backwards\n");
+-    cip = &cdata.curr;
+ 
+-    return calc_corrected_erl_mtime(os_mtime, cip, NULL,
++    return calc_corrected_erl_mtime(os_mtime, &ci, NULL,
+ 				    os_drift_corrected);
+ }
+ 
+_at_@ -1128,13 +1125,13 @@ erts_init_time_sup(int time_correction, ErtsTimeWarpMode time_warp_mode)
+     
+ 	cdatap->drift.intervals[0].time.sys = time_sup.inf.c.sinit;
+ 	cdatap->drift.intervals[0].time.mon = time_sup.inf.c.minit;
+-	cdatap->curr.correction.drift = 0;
+-	cdatap->curr.correction.error = 0;
+-	cdatap->curr.erl_mtime = ERTS_MONOTONIC_BEGIN;
+-	cdatap->curr.os_mtime = time_sup.inf.c.minit;
++	cdatap->insts.curr.correction.drift = 0;
++	cdatap->insts.curr.correction.error = 0;
++	cdatap->insts.curr.erl_mtime = ERTS_MONOTONIC_BEGIN;
++	cdatap->insts.curr.os_mtime = time_sup.inf.c.minit;
+ 	cdatap->last_check = time_sup.inf.c.minit;
+ 	cdatap->short_check_interval = ERTS_INIT_SHORT_INTERVAL_COUNTER;
+-	cdatap->prev = cdatap->curr;
++	cdatap->insts.prev = cdatap->insts.curr;
+ 
+ 	if (!time_sup.r.o.os_corrected_monotonic_time)
+ 	    time_sup.r.o.get_time = get_corrected_time;
+--- a/erts/emulator/test/trace_port_SUITE.erl
++++ b/erts/emulator/test/trace_port_SUITE.erl
+_at_@ -35,7 +35,8 @@
+ 	 fake_schedule_after_getting_linked/1,
+ 	 fake_schedule_after_getting_unlinked/1,
+ 	 gc/1,
+-	 default_tracer/1]).
++	 default_tracer/1,
++	 tracer_port_crash/1]).
+ 
+ -include_lib("test_server/include/test_server.hrl").
+ 
+_at_@ -45,7 +46,7 @@ test_cases() ->
+      fake_schedule_after_register,
+      fake_schedule_after_getting_linked,
+      fake_schedule_after_getting_unlinked, gc,
+-     default_tracer].
++     default_tracer, tracer_port_crash].
+ 
+ suite() -> [{ct_hooks,[ts_install_cth]}].
+ 
+_at_@ -473,6 +474,42 @@ default_tracer(Config) when is_list(Config) ->
+     ?line M = N,
+     ok.
+ 
++tracer_port_crash(Config) when is_list(Config) ->
++    case test_server:is_native(?MODULE) orelse
++	test_server:is_native(lists) of
++	true -> 
++	    {skip,"Native code"};
++	false ->
++	    Tr = start_tracer(Config),
++	    Port = get(tracer_port),
++	    Tracee = spawn(fun () ->
++				   register(trace_port_linker, self()),
++				   link(Port),
++				   receive go -> ok end,
++				   lists:reverse([1,b,c]),
++				   receive die -> ok end
++			   end),
++	    Tr ! {unlink_tracer_port, self()},
++	    receive {unlinked_tracer_port, Tr} -> ok end,
++	    port_control(Port, $c, []), %% Make port commands crash tracer port...
++	    trace_func({lists,reverse,1}, []),
++	    trace_pid(Tracee, true, [call]),
++	    trace_info(Tracee, flags),
++	    trace_info(self(), tracer),
++	    Tracee ! go,
++	    receive after 1000 -> ok end,
++	    case whereis(trace_port_linker) of
++		undefined ->
++		    ok;
++		Id ->
++%		    erts_debug:set_internal_state(available_internal_state, true),
++%		    erts_debug:set_internal_state(abort, {trace_port_linker, Id})
++		    ?t:fail({trace_port_linker, Id})
++	    end,
++	    undefined = process_info(Tracee),
++	    ok
++    end.
++
+ %%% Help functions.
+ 
+ huge_data() -> huge_data(16384).
+_at_@ -631,6 +668,10 @@ tracer_loop(RelayTo, Port) ->
+ 	{Port,{data,Msg}} ->
+ 	    RelayTo ! binary_to_term(Msg),
+ 	    tracer_loop(RelayTo, Port);
++	{unlink_tracer_port, From} ->
++	    unlink(Port),
++	    From ! {unlinked_tracer_port, self()},
++	    tracer_loop(RelayTo, Port);
+ 	Other ->
+ 	    exit({bad_message,Other})
+     end.
+--- a/erts/emulator/test/trace_port_SUITE_data/echo_drv.c
++++ b/erts/emulator/test/trace_port_SUITE_data/echo_drv.c
+_at_@ -1,5 +1,6 @@
+ #include <stdio.h>
+ #include "erl_driver.h"
++#include <errno.h>
+ 
+ 
+ 
+_at_@ -14,6 +15,7 @@ enum e_heavy {
+ typedef struct _erl_drv_data {
+     ErlDrvPort   erlang_port;
+     enum e_heavy heavy;
++    int crash;
+ } EchoDrvData;
+ 
+ static EchoDrvData echo_drv_data, *echo_drv_data_p;
+_at_@ -78,6 +80,7 @@ static EchoDrvData *echo_drv_start(ErlDrvPort port, char *command)
+     echo_drv_data_p = &echo_drv_data;
+     echo_drv_data_p->erlang_port = port;
+     echo_drv_data_p->heavy = heavy_off;
++    echo_drv_data_p->crash = 0;
+     return echo_drv_data_p;
+ }
+ 
+_at_@ -87,6 +90,12 @@ static void echo_drv_stop(EchoDrvData *data_p) {
+ 
+ static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+     EchoDrvData* data_p = (EchoDrvData *) drv_data;
++
++    if (data_p->crash) {
++	driver_failure_posix(data_p->erlang_port, EINTR);
++	return;
++    }
++
+     driver_output(data_p->erlang_port, buf, len);
+     switch (data_p->heavy) {
+     case heavy_off:
+_at_@ -100,6 +109,7 @@ static void echo_drv_output(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) {
+ 	data_p->heavy = heavy_off;
+ 	break;
+     }
++
+ }
+ 
+ static void echo_drv_finish() {
+_at_@ -115,6 +125,8 @@ static ErlDrvSSizeT echo_drv_control(ErlDrvData drv_data,
+     case 'h':
+ 	data_p->heavy = heavy_set;
+ 	break;
++    case 'c':
++	data_p->crash = 1;
+     }
+     return 0;
+ }
+--- a/erts/vsn.mk
++++ b/erts/vsn.mk
+_at_@ -18,7 +18,7 @@
+ # %CopyrightEnd%
+ # 
+ 
+-VSN = 7.0.1
++VSN = 7.0.2
+ 
+ # Port number 4365 in 4.2
+ # Port number 4366 in 4.3
+--- a/lib/runtime_tools/c_src/trace_file_drv.c
++++ b/lib/runtime_tools/c_src/trace_file_drv.c
+_at_@ -327,9 +327,11 @@ static ErlDrvData trace_file_start(ErlDrvPort port, char *buff)
+ 		   | O_BINARY
+ #endif
+ 		   , 0777)) < 0) {
++	int saved_errno = errno;
+ 	if (wrap)
+ 	    driver_free(wrap);
+ 	driver_free(data);
++	errno = saved_errno;
+ 	return ERL_DRV_ERROR_ERRNO;
+     } 
+ 
+_at_@ -525,14 +527,19 @@ static void *my_alloc(size_t size)
+ ** A write wrapper that regards it as an error if not all data was written.
+ */
+ static int do_write(FILETYPE fd, unsigned char *buff, int siz) {
+-    int w = write(fd, buff, siz);
+-    if (w != siz) {
+-	if (w >= 0) {
+-	    errno = ENOSPC;
++    int w;
++    while (1) {
++	w = write(fd, buff, siz);
++	if (w < 0 && errno == EINTR)
++	    continue;
++	else if (w != siz) {
++	    if (w >= 0) {
++		errno = ENOSPC;
++	    }
++	    return -1;
+ 	}
+-	return -1;
++	return siz;
+     }
+-    return siz;
+ }
+ 
+ /*
+_at_@ -627,8 +634,10 @@ static void close_unlink_port(TraceFileData *data)
+ */
+ static int wrap_file(TraceFileData *data) {
+     if (my_flush(data) < 0) {
++	int saved_errno = errno;
+ 	close(data->fd);
+ 	data->fd = -1;
++	errno = saved_errno;
+ 	return -1;
+     }
+     close(data->fd);
+_at_@ -644,12 +653,15 @@ static int wrap_file(TraceFileData *data) {
+ 	next_name(&data->wrap->del);
+     }
+     next_name(&data->wrap->cur);
++try_open:
+     data->fd = open(data->wrap->cur.name, O_WRONLY | O_TRUNC | O_CREAT
+ #ifdef O_BINARY
+ 	      | O_BINARY
+ #endif
+ 	      , 0777);
+     if (data->fd < 0) {
++	if (errno == EINTR)
++	    goto try_open;
+ 	data->fd = -1;
+ 	return -1;
+     }
+--- a/lib/runtime_tools/doc/src/notes.xml
++++ b/lib/runtime_tools/doc/src/notes.xml
+_at_@ -32,6 +32,23 @@
+   <p>This document describes the changes made to the Runtime_Tools
+     application.</p>
+ 
++<section><title>Runtime_Tools 1.9.1</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    The <c>trace_file_drv</c> did not handle <c>EINTR</c>
++	    correct which caused it to fail when the runtime system
++	    received a signal.</p>
++          <p>
++	    Own Id: OTP-12890 Aux Id: seq12885 </p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>Runtime_Tools 1.9</title>
+ 
+     <section><title>Improvements and New Features</title>
+--- a/lib/runtime_tools/vsn.mk
++++ b/lib/runtime_tools/vsn.mk
+_at_@ -1 +1 @@
+-RUNTIME_TOOLS_VSN = 1.9
++RUNTIME_TOOLS_VSN = 1.9.1
+--- a/otp_versions.table
++++ b/otp_versions.table
+_at_@ -1,3 +1,4 @@
++OTP-18.0.2 : erts-7.0.2 runtime_tools-1.9.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :
+ OTP-18.0.1 : erts-7.0.1 # asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 :
+ OTP-18.0 : asn1-4.0 common_test-1.11 compiler-6.0 cosEvent-2.2 cosEventDomain-1.2 cosFileTransfer-1.2 cosNotification-1.2 cosProperty-1.2 cosTime-1.2 cosTransactions-1.3 crypto-3.6 debugger-4.1 dialyzer-2.8 diameter-1.10 edoc-0.7.17 eldap-1.2 erl_docgen-0.4 erl_interface-3.8 erts-7.0 et-1.5.1 eunit-2.2.10 gs-1.6 hipe-3.12 ic-4.4 inets-6.0 jinterface-1.6 kernel-4.0 megaco-3.18 mnesia-4.13 observer-2.1 odbc-2.11 orber-3.8 os_mon-2.4 ose-1.1 otp_mibs-1.1 parsetools-2.1 percept-0.8.11 public_key-1.0 reltool-0.7 runtime_tools-1.9 sasl-2.5 snmp-5.2 ssh-4.0 ssl-7.0 stdlib-2.5 syntax_tools-1.7 test_server-3.9 tools-2.8 typer-0.9.9 webtool-0.9 wx-1.4 xmerl-1.3.8 # :
+ OTP-17.5.6 : inets-5.10.9 ssh-3.2.4 ssl-6.0.1 # asn1-3.0.4 common_test-1.10.1 compiler-5.0.4 cosEvent-2.1.15 cosEventDomain-1.1.14 cosFileTransfer-1.1.16 cosNotification-1.1.21 cosProperty-1.1.17 cosTime-1.1.14 cosTransactions-1.2.14 crypto-3.5 debugger-4.0.3 dialyzer-2.7.4 diameter-1.9.2 edoc-0.7.16 eldap-1.1.1 erl_docgen-0.3.7 erl_interface-3.7.20 erts-6.4.1 et-1.5 eunit-2.2.9 gs-1.5.16 hipe-3.11.3 ic-4.3.6 jinterface-1.5.12 kernel-3.2 megaco-3.17.3 mnesia-4.12.5 observer-2.0.4 odbc-2.10.22 orber-3.7.1 os_mon-2.3.1 ose-1.0.2 otp_mibs-1.0.10 parsetools-2.0.12 percept-0.8.10 public_key-0.23 reltool-0.6.6 runtime_tools-1.8.16 sasl-2.4.1 snmp-5.1.2 stdlib-2.4 syntax_tools-1.6.18 test_server-3.8.1 tools-2.7.2 typer-0.9.8 webtool-0.8.10 wx-1.3.3 xmerl-1.3.7 :
diff --git a/testing/erlang/APKBUILD b/testing/erlang/APKBUILD
index 2d4f2bd..79f0253 100644
--- a/testing/erlang/APKBUILD
+++ b/testing/erlang/APKBUILD
_at_@ -2,7 +2,7 @@
 # Maintainer: Marlus Saraiva <marlus.saraiva_at_gmail.com>
 
 pkgname=erlang
-pkgver=18.0.1
+pkgver=18.0.2
 _srcver=18.0
 pkgrel=0
 pkgdesc="General-purpose programming language and runtime environment"
_at_@ -76,7 +76,8 @@ source="http://www.erlang.org/download/otp_src_$_srcver.tar.gz
         0010-fix-nteventlog-remove.patch
         0020-remove-private-unit32.patch
         0030-replace_glibc_check.patch
-        0040-otp-update-version-18.0.1.patch"
+        0040-otp-update-version-18.0.1.patch
+        0050-otp-update-version-18.0.2.patch"
 
 _builddir="$srcdir"/otp_src_$_srcver
 
_at_@ -219,7 +220,8 @@ b438c37818b5c82443682c3693dd7e53  0007-Split-off-webtool-dependency-from-tools.p
 fcb02f2cc2050789aa85f6f0084836c3  0010-fix-nteventlog-remove.patch
 062605d7f01f4685f1897ba2decc23a8  0020-remove-private-unit32.patch
 7a5c956b7bf79e34a0f980d1e2a65bee  0030-replace_glibc_check.patch
-e621bd76d8e19af2d60e4d1a11ddbca3  0040-otp-update-version-18.0.1.patch"
+e621bd76d8e19af2d60e4d1a11ddbca3  0040-otp-update-version-18.0.1.patch
+4ade398725d713b5cf577c4c072c2d95  0050-otp-update-version-18.0.2.patch"
 sha256sums="a0b69da34b4f218eb7d63d9e96fc120aa7257bb6c37a0f40fb388e188b4111aa  otp_src_18.0.tar.gz
 536e78192f915733cbbb264883af6d9b11c9e70c2c4d3d825b58c4dbec36db86  0001-Do-not-format-man-pages-and-do-not-install-miscellan.patch
 b2e5844215d7f5f5026a77342dd698d16103cc726d23f8265bcc8399d1a82bb9  0002-Remove-rpath.patch
_at_@ -231,7 +233,8 @@ b810ef25504fbce3f9a0d4ae1e02fc4225b01fd68daa88566f6f8de37e26b351  0006-Do-not-in
 70dd9d1c4914ccecdbb3623ee23eb9ae3c8df8a5e40e2e0177c754440afe55f9  0010-fix-nteventlog-remove.patch
 0b63ff5ce4e642d4225d5cc4d52d88dd5daf83ce5a2549ba0e5a14ce05e17ac2  0020-remove-private-unit32.patch
 e3158dbb4bcb4677ceda39a374326c069de78a52e598ef8169a288b86a040a62  0030-replace_glibc_check.patch
-a014ad5c5da2512672af7a98ca072d6aa2615af2d1cc8e67a6cc611096cc922a  0040-otp-update-version-18.0.1.patch"
+a014ad5c5da2512672af7a98ca072d6aa2615af2d1cc8e67a6cc611096cc922a  0040-otp-update-version-18.0.1.patch
+c51691da93e54e6b42c234706070dae74079cea00e6b720c9513663b2d7ed0a8  0050-otp-update-version-18.0.2.patch"
 sha512sums="84ec2a3834270c1babe153572d6187faa36c12128e604037d55be01719788c0dd79d46769ea7090d530b746206a25fe02346b02849abee10ee41ed4ac7567c02  otp_src_18.0.tar.gz
 172f9b0f61748bf2f04737df0451bcc9c0812db0f365f0ef7c7c244fceb991987f79a5274eea578a89cc7d077f84645d1395d9dbcbf14010268b896a080c2ccf  0001-Do-not-format-man-pages-and-do-not-install-miscellan.patch
 97c40c185b71b23ffcb924639af390b9a0be897070e396a9413e193e6d43048dfe3b86bcd0c5598b81a66ce1349de9e09f5228a452b51b6612cd947bbafb6377  0002-Remove-rpath.patch
_at_@ -243,4 +246,5 @@ d65fcfc3a9441941c6292c33d354964a82da11cc7a411dd0440719e490075ed588c1e70690e80650
 ccd876c5e3e370a3cd85907240546be6be124f8b38e19fae1b152f6858ebd3f4f7421931a8e314dddf019ed9c75cc453c08633b20fa08c05810f66c92725a3ed  0010-fix-nteventlog-remove.patch
 18f70c3a99ac8c44bc9d90dc3f0c072ad4df4ffe57a8d0677087c9e940ba138d7a7698d5cdbbe14875a6012d353a679fdb33d40fca3a3211f712af8c4b0cb0b4  0020-remove-private-unit32.patch
 b554882bee1a70322cc8c5b973986047deaf4528fe1371df39cf72b27b2497a859463bdf8847ea6ea96cb0caaa6bd143c96a5dee28839164a547a66a30fcffd0  0030-replace_glibc_check.patch
-5f6f5856fc60f7bc333fb2736bcf0d8dd475658621bb8ded8a9f664bb045ba5b0768ec990a05e5c35c5dfaa284f10567ff61b7a3c521a907553561c50c068ad1  0040-otp-update-version-18.0.1.patch"
+5f6f5856fc60f7bc333fb2736bcf0d8dd475658621bb8ded8a9f664bb045ba5b0768ec990a05e5c35c5dfaa284f10567ff61b7a3c521a907553561c50c068ad1  0040-otp-update-version-18.0.1.patch
+cae82f07a8eb811f47a2a7553626d536e16a368fe8292dcee6c991f4f069e7821e0a2310cc86f65313b87ac6691a406ca92fc36b7ab32079b060813602c9f16a  0050-otp-update-version-18.0.2.patch"
-- 
2.4.1
---
Unsubscribe:  alpine-aports+unsubscribe_at_lists.alpinelinux.org
Help:         alpine-aports+help_at_lists.alpinelinux.org
---
Received on Wed Jul 15 2015 - 20:24:14 GMT