After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 618308 - Tiles get destroy before the end of an animation
Tiles get destroy before the end of an animation
Status: RESOLVED FIXED
Product: libchamplain
Classification: Core
Component: General
0.5.x
Other Linux
: Normal normal
: 0.6
Assigned To: libchamplain-maint
libchamplain-maint
Depends on:
Blocks:
 
 
Reported: 2010-05-10 20:26 UTC by Emmanuel Rodriguez
Modified: 2010-05-23 19:59 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Prevent a tile to be destroyed before the end of an animation (1.21 KB, patch)
2010-05-10 20:26 UTC, Emmanuel Rodriguez
none Details | Review
Add debug (1.40 KB, patch)
2010-05-11 20:37 UTC, Emmanuel Rodriguez
none Details | Review
Possible fix (3.07 KB, patch)
2010-05-18 22:49 UTC, Jiri Techet
none Details | Review

Description Emmanuel Rodriguez 2010-05-10 20:26:34 UTC
Created attachment 160765 [details] [review]
Prevent a tile to be destroyed before the end of an animation

If we zoom in very fast and tiles haven't finished their animation then the program will crash because the animation completed callback will be called with a tile that's already destroyed.

This patch prevents the tiles for dying until the animation is not completed.
Comment 1 Jiri Techet 2010-05-10 22:41:12 UTC
Do you actually experience the crash or you think there _might_ be a crash? No crash here no matter how fast I zoom in.

Notice the difference what a tile is now - it _is_ an actor - not like before when a tile was an object that _contained_ an actor. So before if a tile was destroyed the actor could still exist and you really had to do the check you are suggesting. But now if the tile is destroyed, the actor is destroyed too because the tile _is_ an actor. So if it gets destroyed while fading in, the signal "completed" cannot be emitted because the actor doesn't exist any more so fade_in_completed() cannot be called in this case.

Check my email about how things work now in the libchamplain mailing list (written about two months ago). The most important feature of the new solution is that I _never_ call _ref() _unref() on tiles. The tile sources just watch the tile through weak pointers and if the tile is destroyed while loading, they just stop loading it. The nice result is that things are much simpler now and that there are no memory leaks (I hope). Before, every tile was leaked and it reffing and unreffing was so complicated that it was almost impossible to find where the leak happens.
Comment 2 Emmanuel Rodriguez 2010-05-11 05:58:56 UTC
> Do you actually experience the crash or you think there _might_ be a crash? No
> crash here no matter how fast I zoom in.
I definitely experience a crash. I had to go through gdb to see that callback would be called after the tile gets destroyed.

I added print statements in the tile's destructor, before the callback gets created and in the callback and I can see that tiles can get destroyed before the animation is over.

> So before if a tile was destroyed the actor could still exist and you really had to do the check you are suggesting. But now if the tile is destroyed, the actor is destroyed too because the tile _is_ an actor.
I saw that and I was also guessing that something strange was going on. Maybe my g_object_unref patch is braking things?

One thing that I noticed is that while the tile is an actor. It's not the actor passed to the animation! The animation will keep a reference to it's actor and make it leave longer. The problem that I experience is with the tile getting destroyed.
Comment 3 Jiri Techet 2010-05-11 09:39:47 UTC
> I saw that and I was also guessing that something strange was going on. Maybe
my g_object_unref patch is braking things?

I think this is the case. Could you test just the original version with clutter_actor_destroy() instead of g_object_unref()? I really can't reproduce the crash here even when zooming in quickly with mouse wheel.

The the way I hope it works is: we have two actors - the tile actor (ClutterGroup) and the content actor (ClutterActor), which is inside it. The animation is created for the content actor, but if the tile actor gets destroyed, the content actor gets destroyed together with it - together with the animation.
Comment 4 Emmanuel Rodriguez 2010-05-11 20:28:35 UTC
I reverted my patch and executed the launcher demo. I have plenty of warnings when zooming in/out. If I turn all warnings into fatal errros I get a stack trace that seems quite similar.

Steps to reproduce:

gcc -O0 -g3 -I. -o launcher launcher.c markers.o `pkg-config --cflags --libs champlain-memphis-0.5 memphis-0.2`

G_DEBUG=fatal_warnings  gdb --args ./launcher

GNU gdb (GDB) 7.0-ubuntu
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/emmanuel/git/c/champlain-c/demos/launcher...done.
(gdb) run
Starting program: /home/emmanuel/git/c/champlain-c/demos/launcher 
[Thread debugging using libthread_db enabled]
[New Thread 0x7fffeca45910 (LWP 9270)]
[Thread 0x7fffeca45910 (LWP 9270) exited]
[New Thread 0x7fffeca45910 (LWP 9271)]
[Thread 0x7fffeca45910 (LWP 9271) exited]
[New Thread 0x7fffeca45910 (LWP 9272)]
[New Thread 0x7fffeaf9b910 (LWP 9273)]
[New Thread 0x7fffea79a910 (LWP 9274)]
[Thread 0x7fffea79a910 (LWP 9274) exited]
[Thread 0x7fffeaf9b910 (LWP 9273) exited]
[Thread 0x7fffeca45910 (LWP 9272) exited]
[New Thread 0x7fffeca45910 (LWP 9275)]
[Thread 0x7fffeca45910 (LWP 9275) exited]
[New Thread 0x7fffeca45910 (LWP 9276)]

GLib-GObject-WARNING **: invalid uninstantiatable type `(null)' in cast to `ClutterGroup'
aborting...

Program received signal SIGABRT, Aborted.
0x00007ffff41504b5 in *__GI_raise (sig=<value optimized out>) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
64	../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
	in ../nptl/sysdeps/unix/sysv/linux/raise.c
(gdb) bt
  • #0 *__GI_raise
    at ../nptl/sysdeps/unix/sysv/linux/raise.c line 64
  • #1 *__GI_abort
    at abort.c line 92
  • #2 IA__g_logv
    at /build/buildd/glib2.0-2.22.3/glib/gmessages.c line 549
  • #3 IA__g_log
    at /build/buildd/glib2.0-2.22.3/glib/gmessages.c line 569
  • #4 IA__g_type_check_instance_cast
    at /build/buildd/glib2.0-2.22.3/gobject/gtype.c line 3742
  • #5 fade_in_completed
    at champlain-tile.c line 514
  • #6 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.22.3/gobject/gclosure.c line 767
  • #7 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 3247
  • #8 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 2980
  • #9 IA__g_signal_emit
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 3037
  • #10 IA__g_closure_invoke
    at /build/buildd/glib2.0-2.22.3/gobject/gclosure.c line 767
  • #11 signal_emit_unlocked_R
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 3247
  • #12 IA__g_signal_emit_valist
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 2980
  • #13 IA__g_signal_emit
    at /build/buildd/glib2.0-2.22.3/gobject/gsignal.c line 3037
  • #14 clutter_timeline_do_frame
    at ./clutter-timeline.c line 657
  • #15 clutter_timeline_do_tick
    at ./clutter-timeline.c line 1248
  • #16 _clutter_master_clock_advance
    at ./clutter-master-clock.c line 436
  • #17 clutter_clock_dispatch
    at ./clutter-master-clock.c line 286
  • #18 g_main_dispatch
    at /build/buildd/glib2.0-2.22.3/glib/gmain.c line 1960
  • #19 IA__g_main_context_dispatch
    at /build/buildd/glib2.0-2.22.3/glib/gmain.c line 2513
  • #20 g_main_context_iterate
    at /build/buildd/glib2.0-2.22.3/glib/gmain.c line 2591
  • #21 IA__g_main_loop_run
    at /build/buildd/glib2.0-2.22.3/glib/gmain.c line 2799
  • #22 clutter_main
    at ./clutter-main.c line 593
  • #23 main
    at launcher.c line 144

Comment 5 Emmanuel Rodriguez 2010-05-11 20:37:18 UTC
Created attachment 160862 [details] [review]
Add debug

This patches adds debug in order to monitor the life time of tiles.
Comment 6 Emmanuel Rodriguez 2010-05-11 20:43:54 UTC
If I run the launcher demo and I zoom in and out in a very fast way I can make the demo crash if warnings are fatal. Once the demo is crashed I can see that if I follow the activity of the last tile that strange things happen:

init 0x2478e00
animation 0x2478e00
fade_in_completed 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
animation 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
fade_in_completed 0x2478e00

Keep in mind that the memory allocator likes to reuse the same memory addresses so it's normal to see a lot of init/finalize combos. Each fade_in_completed call should be preceded by an animation call.

As you can see in this simplified version that's not what happened:

init 0x2478e00
animation 0x2478e00
fade_in_completed 0x2478e00
finalize 0x2478e00
init 0x2478e00
(...)
init 0x2478e00
animation 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
init 0x2478e00
finalize 0x2478e00
fade_in_completed 0x2478e00
Comment 7 Emmanuel Rodriguez 2010-05-11 20:52:42 UTC
Applying the patch fixes the crash.
Comment 8 Jiri Techet 2010-05-11 23:57:50 UTC
No crash and no fatal warnings here :-( [one usually doesn't use sad smilies in this context :-)]. I have even increased the animation time to 1 second to be sure that the tile gets destroyed before the end of the animation. This is what I get when zooming in/out quickly with mouse wheel:

init 0x1409420
init 0x138e910
init 0x1408fc0
init 0x14091f0
init 0x138efa0
init 0x14082a0
init 0x14084d0
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x138e6e0
init 0x138e280
init 0x1408070
init 0x138e4b0
init 0x138eb40
init 0x138ed70
init 0x1408930
animation 0x1409420
animation 0x138e910
animation 0x1408fc0
animation 0x14091f0
animation 0x138efa0
animation 0x14082a0
animation 0x14084d0
animation 0x138fcc0
animation 0x138fa90
animation 0x138f860
animation 0x138f630
animation 0x138f400
animation 0x138f1d0
animation 0x138e6e0
animation 0x138e280
animation 0x138e4b0
animation 0x138eb40
animation 0x138ed70
animation 0x1408930
animation 0x1408070
finalize 0x1409420
finalize 0x138e910
finalize 0x1408fc0
finalize 0x14091f0
finalize 0x138efa0
finalize 0x14082a0
finalize 0x14084d0
finalize 0x138fcc0
finalize 0x138fa90
finalize 0x138f860
finalize 0x138f630
finalize 0x138f400
finalize 0x138f1d0
finalize 0x138e6e0
finalize 0x138e280
finalize 0x1408070
finalize 0x138e4b0
finalize 0x138eb40
finalize 0x138ed70
finalize 0x1408930
init 0x138e4b0
init 0x1408070
init 0x138e280
init 0x138e6e0
init 0x1408930
init 0x138ed70
init 0x138eb40
init 0x138f1d0
init 0x138f400
init 0x138f630
init 0x138f860
init 0x138fa90
init 0x138fcc0
init 0x14084d0
init 0x14082a0
init 0x138efa0
init 0x1408700
init 0x1408d90
init 0x1408b60
init 0x14091f0
animation 0x1408070
animation 0x138f400
finalize 0x138e4b0
finalize 0x1408070
finalize 0x138e280
finalize 0x138e6e0
finalize 0x1408930
finalize 0x138ed70
finalize 0x138eb40
finalize 0x138f1d0
finalize 0x138f400
finalize 0x138f630
finalize 0x138f860
finalize 0x138fa90
finalize 0x138fcc0
finalize 0x14084d0
finalize 0x14082a0
finalize 0x138efa0
finalize 0x1408700
finalize 0x1408d90
finalize 0x1408b60
finalize 0x14091f0
init 0x1408700
init 0x138efa0
init 0x14082a0
init 0x14084d0
init 0x14091f0
init 0x1408b60
init 0x1408d90
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x138eb40
init 0x138ed70
init 0x1408930
init 0x1408fc0
init 0x138e910
init 0x1409420
init 0x138e6e0
finalize 0x1408700
finalize 0x138efa0
finalize 0x14082a0
finalize 0x14084d0
finalize 0x14091f0
finalize 0x1408b60
finalize 0x1408d90
finalize 0x138fcc0
finalize 0x138fa90
finalize 0x138f860
finalize 0x138f630
finalize 0x138f400
finalize 0x138f1d0
finalize 0x138eb40
finalize 0x138ed70
finalize 0x1408930
finalize 0x1408fc0
finalize 0x138e910
finalize 0x1409420
finalize 0x138e6e0
init 0x1408fc0
init 0x1408930
init 0x138ed70
init 0x138eb40
init 0x138e6e0
init 0x1409420
init 0x138e910
init 0x138f1d0
init 0x138f400
init 0x138f630
init 0x138f860
init 0x138fa90
init 0x138fcc0
init 0x1408d90
init 0x1408b60
init 0x14091f0
init 0x138e280
init 0x1408070
init 0x138e4b0
init 0x14084d0
animation 0x1408fc0
animation 0x1408930
animation 0x138ed70
animation 0x138eb40
finalize 0x1408fc0
finalize 0x1408930
finalize 0x138ed70
finalize 0x138eb40
finalize 0x138e6e0
finalize 0x1409420
finalize 0x138e910
finalize 0x138f1d0
finalize 0x138f400
finalize 0x138f630
finalize 0x138f860
finalize 0x138fa90
finalize 0x138fcc0
finalize 0x1408d90
finalize 0x1408b60
finalize 0x14091f0
finalize 0x138e280
finalize 0x1408070
finalize 0x138e4b0
finalize 0x14084d0
init 0x138e280
init 0x14091f0
init 0x1408b60
init 0x1408d90
init 0x14084d0
init 0x138e4b0
init 0x1408070
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x138e910
init 0x1409420
init 0x138e6e0
init 0x14082a0
init 0x138efa0
init 0x1408700
init 0x138eb40
finalize 0x138e280
finalize 0x14091f0
finalize 0x1408b60
finalize 0x1408d90
finalize 0x14084d0
finalize 0x138e4b0
finalize 0x1408070
finalize 0x138fcc0
finalize 0x138fa90
finalize 0x138f860
finalize 0x138f630
finalize 0x138f400
finalize 0x138f1d0
finalize 0x138e910
finalize 0x1409420
finalize 0x138e6e0
finalize 0x14082a0
finalize 0x138efa0
finalize 0x1408700
finalize 0x138eb40
init 0x14082a0
init 0x138e6e0
init 0x1409420
init 0x138e910
init 0x138eb40
init 0x1408700
init 0x138efa0
init 0x138f1d0
init 0x138f400
init 0x138f630
init 0x138f860
init 0x138fa90
init 0x138fcc0
init 0x1408070
init 0x138e4b0
init 0x14084d0
init 0x138ed70
init 0x1408930
init 0x1408fc0
init 0x1408d90
animation 0x138e6e0
animation 0x14082a0
animation 0x1409420
animation 0x138e910
animation 0x1408700
animation 0x138eb40
finalize 0x14082a0
finalize 0x138e6e0
finalize 0x1409420
finalize 0x138e910
finalize 0x138eb40
finalize 0x1408700
finalize 0x138efa0
finalize 0x138f1d0
finalize 0x138f400
finalize 0x138f630
finalize 0x138f860
finalize 0x138fa90
finalize 0x138fcc0
finalize 0x1408070
finalize 0x138e4b0
finalize 0x14084d0
finalize 0x138ed70
finalize 0x1408930
finalize 0x1408fc0
finalize 0x1408d90
init 0x138ed70
init 0x14084d0
init 0x138e4b0
init 0x1408070
init 0x1408d90
init 0x1408fc0
init 0x1408930
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x138efa0
init 0x1408700
init 0x138eb40
init 0x1408b60
init 0x14091f0
init 0x138e280
init 0x138e910
finalize 0x138ed70
finalize 0x14084d0
finalize 0x138e4b0
finalize 0x1408070
finalize 0x1408d90
finalize 0x1408fc0
finalize 0x1408930
finalize 0x138fcc0
finalize 0x138fa90
finalize 0x138f860
finalize 0x138f630
finalize 0x138f400
finalize 0x138f1d0
finalize 0x138efa0
finalize 0x1408700
finalize 0x138eb40
finalize 0x1408b60
finalize 0x14091f0
finalize 0x138e280
finalize 0x138e910
init 0x1408b60
init 0x138eb40
init 0x1408700
init 0x138efa0
init 0x138e910
init 0x138e280
init 0x14091f0
init 0x138f1d0
init 0x138f400
init 0x138f630
init 0x138f860
init 0x138fa90
init 0x138fcc0
init 0x1408930
init 0x1408fc0
init 0x1408d90
init 0x1409420
init 0x138e6e0
init 0x14082a0
init 0x1408070
finalize 0x1408b60
finalize 0x138eb40
finalize 0x1408700
finalize 0x138efa0
finalize 0x138e910
finalize 0x138e280
finalize 0x14091f0
finalize 0x138f1d0
finalize 0x138f400
finalize 0x138f630
finalize 0x138f860
finalize 0x138fa90
finalize 0x138fcc0
finalize 0x1408930
finalize 0x1408fc0
finalize 0x1408d90
finalize 0x1409420
finalize 0x138e6e0
finalize 0x14082a0
finalize 0x1408070
init 0x1409420
init 0x1408d90
init 0x1408fc0
init 0x1408930
init 0x1408070
init 0x14082a0
init 0x138e6e0
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x14091f0
init 0x138e280
init 0x138e910
init 0x138e4b0
init 0x14084d0
init 0x138ed70
init 0x138efa0
finalize 0x1409420
finalize 0x1408d90
finalize 0x1408fc0
finalize 0x1408930
finalize 0x1408070
finalize 0x14082a0
finalize 0x138e6e0
finalize 0x138fcc0
finalize 0x138fa90
finalize 0x138f860
finalize 0x138f630
finalize 0x138f400
finalize 0x138f1d0
finalize 0x14091f0
finalize 0x138e280
finalize 0x138e910
finalize 0x138e4b0
finalize 0x14084d0
finalize 0x138ed70
finalize 0x138efa0
init 0x138e4b0
init 0x138e910
init 0x138e280
init 0x14091f0
init 0x138efa0
init 0x138ed70
init 0x14084d0
init 0x138f1d0
init 0x138f400
init 0x138f630
init 0x138f860
init 0x138fa90
init 0x138fcc0
init 0x138e6e0
init 0x14082a0
init 0x1408070
init 0x1408700
init 0x138eb40
init 0x1408b60
init 0x1408930
finalize 0x138e4b0
finalize 0x138e910
finalize 0x138e280
finalize 0x14091f0
finalize 0x138efa0
finalize 0x138ed70
finalize 0x14084d0
finalize 0x138f1d0
finalize 0x138f400
finalize 0x138f630
finalize 0x138f860
finalize 0x138fa90
finalize 0x138fcc0
finalize 0x138e6e0
finalize 0x14082a0
finalize 0x1408070
finalize 0x1408700
finalize 0x138eb40
finalize 0x1408b60
finalize 0x1408930
init 0x1408700
init 0x1408070
init 0x14082a0
init 0x138e6e0
init 0x1408930
init 0x1408b60
init 0x138eb40
init 0x138fcc0
init 0x138fa90
init 0x138f860
init 0x138f630
init 0x138f400
init 0x138f1d0
init 0x14084d0
init 0x138ed70
init 0x138efa0
init 0x1408fc0
init 0x1408d90
init 0x1409420
init 0x14091f0
animation 0x1408700
animation 0x1408070
animation 0x14082a0
animation 0x138e6e0
animation 0x1408930
animation 0x1408b60
animation 0x138eb40
animation 0x138fcc0
animation 0x138fa90
animation 0x138f860
animation 0x138f630
animation 0x138f400
animation 0x138f1d0
animation 0x14084d0
animation 0x138ed70
animation 0x138efa0
animation 0x1408fc0
animation 0x1408d90
animation 0x1409420
animation 0x14091f0
fade_in_completed 0x1408b60
fade_in_completed 0x1408930
fade_in_completed 0x138e6e0
fade_in_completed 0x14082a0
fade_in_completed 0x1408070
fade_in_completed 0x1408700
fade_in_completed 0x138f400
fade_in_completed 0x138f630
fade_in_completed 0x138f860
fade_in_completed 0x138fa90
fade_in_completed 0x138fcc0
fade_in_completed 0x138eb40
fade_in_completed 0x1408d90
fade_in_completed 0x1408fc0
fade_in_completed 0x138efa0
fade_in_completed 0x138ed70
fade_in_completed 0x14084d0
fade_in_completed 0x138f1d0
fade_in_completed 0x14091f0
fade_in_completed 0x1409420

As you can see, fade_in_completed() is executed only after I stop zooming - before, the tile gets destroyed without fade_in_completed() being executed.

Let's try to eliminate other sources of bugs. I'm using Ubuntu Lucid with clutter 1.2.4 - could you install this version of clutter if you are using something different? Second, just do clean git clone of libchamplain in case something is hiding in your source tree. Then, please, test again.

I'm not against fixing this issue, I'd just like to know what's going on before applying a patch.
Comment 9 Emmanuel Rodriguez 2010-05-18 19:02:46 UTC
I have reseted my HEAD to the SHA1 3155d09d9b773398473709b1af41f496a3a5e17e and compiled and installed that version of libchamplain [1].

I've executed the program as documented on comment #4 and I get the same crash. My system is Ubuntu 9.10 with an NVIDIA card and cluttter:
libclutter-1.0-0   1.0.6-0ubuntu1

[1] This requires the manual creation of the file ChangeLog (`touch ChangeLog` works file).
Comment 10 Jiri Techet 2010-05-18 22:49:59 UTC
Created attachment 161390 [details] [review]
Possible fix

OK, I have simplified the code a bit and it might help - would you test the attached patch?
Comment 11 Jiri Techet 2010-05-22 23:21:25 UTC
I've committed a slightly modified version of this patch so please test rather what's in git now. I've also fixed a bug in launcher-gtk that caused crash at program shutdown.
Comment 12 Emmanuel Rodriguez 2010-05-23 18:26:56 UTC
The patch works. I can't reproduce the crash.
Comment 13 Jiri Techet 2010-05-23 19:59:47 UTC
Perfect, thanks.