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 792219 - Critical warning when TLS connection is dropped
Critical warning when TLS connection is dropped
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: network
2.54.x
Other Linux
: Normal normal
: ---
Assigned To: Michael Catanzaro
gtkdev
Depends on:
Blocks:
 
 
Reported: 2018-01-04 22:48 UTC by Michael Gratton
Modified: 2018-03-06 02:48 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Input/output streams should expect to outlast their GTlsConnection (8.07 KB, patch)
2018-03-01 21:44 UTC, Michael Catanzaro
committed Details | Review

Description Michael Gratton 2018-01-04 22:48:23 UTC
Geary occasionally emits the following warning when the underlying connection to its mail server has dropped, and it finally notices it after attempting to send some command which times out:

>  [deb] 23:34:19 29.993534 imap-client-connection.vala:799: [0015/203.18.245.241:993/GEARY_IMAP_CLIENT_CONNECTION_STATE_DEIDLING] on_cmd_timeout
>  [deb] 23:34:19 0.000072 imap-client-session.vala:1866: [0015/mail.quuxo.net/default:993 GEARY_IMAP_CLIENT_SESSION_STATE_SELECTED] Receive failed: No response to command(s) after 30 seconds
>  [deb] 23:34:19 0.000035 imap-client-session.vala:1575: [0015/mail.quuxo.net/default:993 GEARY_IMAP_CLIENT_SESSION_STATE_SELECTED] Receive error, disconnecting: No response to command(s) after 30 seconds
> [snip]
> (geary:3012): GLib-Net-CRITICAL **: g_tls_output_stream_gnutls_write: assertion 'conn != NULL' failed


Backtrace for this looks as follows:

Thread 860 "pool" received signal SIGTRAP, Trace/breakpoint trap.

Thread 140732659660544 (LWP 10760)

  • #0 _g_log_abort
    at ../../../../glib/gmessages.c line 554
  • #1 g_logv
    at ../../../../glib/gmessages.c line 1362
  • #2 g_log
    at ../../../../glib/gmessages.c line 1403
  • #3 g_return_if_fail_warning
    at ../../../../glib/gmessages.c line 2702
  • #4 g_tls_output_stream_gnutls_write
    at gtlsoutputstream-gnutls.c line 69
  • #5 g_output_stream_write
    at ../../../../gio/goutputstream.c line 222
  • #6 g_output_stream_write_all
    at ../../../../gio/goutputstream.c line 281
  • #7 flush_buffer
    at ../../../../gio/gbufferedoutputstream.c line 422
  • #8 flush_buffer_thread
    at ../../../../gio/gbufferedoutputstream.c line 664
  • #9 g_task_thread_pool_thread
    at ../../../../gio/gtask.c line 1328
  • #10 g_thread_pool_thread_proxy
    at ../../../../glib/gthreadpool.c line 307
  • #11 g_thread_proxy
    at ../../../../glib/gthread.c line 784
  • #12 start_thread
    at pthread_create.c line 465
  • #13 clone
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S line 95

GBufferedOutputStream seems to be attempting to flush buffered data when the base stream has closed due to some network failure, resulting in a critical warning. However since a GTLS stream is involved, it looks like it might be the same issue as Bug 738277.
Comment 1 Michael Catanzaro 2018-02-12 03:01:35 UTC
Bug #738277 is unrelated.

CC Olivier since he changed this code to use GWeakRef in bug #735754, though the bug actually predates that.

I'm not sure about this. I *think* the only problem here is that criticals are being printed. It's legit for the GTlsOutputStreamGnutls to outlive its associated GTlsConnectionGnutls; all you have to do to make that happen is to ref the GOutputStream (which GBufferedOutputStream's parent class, GFilterOutputStream, does) and then somewhere unref the GTlsConnection. Then you would expect to have a nonfunctional GOutputStream, but one that probably should not be emitting critical warnings like this. So I *think* we should just replace the g_return_val_if_fail() with normal returns, figure out a suitable GError to bubble up (G_IO_ERROR_CONNECTION_CLOSED seems good to me), and move on.

My only hesitation is that I'm sure the g_return_val_if_fail()s are there to warn us that GTlsConnectionGnutls should in fact not be destroyed at this point. But that seems to simply be a programming error.

The other problem is that it's probably a bug in Geary -- or whatever is creating the GBufferedOutputStream -- that the GBufferedOutputStream is destroyed by the GTlsConnection. Michael, do you have any idea where the GBufferedOutputStream is coming from?
Comment 2 Michael Catanzaro 2018-02-12 03:14:38 UTC
One complication is that g_pollable_output_stream_create_source() and g_pollable_input_stream_create_source() are not fallible, so I guess we have to return a dummy GSource in this case. That's not great, but should be OK.
Comment 3 Michael Catanzaro 2018-02-12 03:16:02 UTC
(In reply to Michael Catanzaro from comment #1)
> The other problem is that it's probably a bug in Geary -- or whatever is
> creating the GBufferedOutputStream -- that the GBufferedOutputStream is
> destroyed by the GTlsConnection.

"by" -> "before"
Comment 4 Michael Gratton 2018-02-12 03:28:00 UTC
(In reply to Michael Catanzaro from comment #1)
> The other problem is that it's probably a bug in Geary -- or whatever is
> creating the GBufferedOutputStream -- that the GBufferedOutputStream is
> destroyed by the GTlsConnection. Michael, do you have any idea where the
> GBufferedOutputStream is coming from?

Yeah, I was also wondering if that was the case. When I first created this bug Geary was not explicitly closing the GBufferedOutputStream, and relying on it cleaning itself up when deallocated. I pushed commit 479e9946 just a few weeks ago which explicitly closes GBufferedOutputStream before closing the GTlsConnection. I was expecting the critical to go away, but I think I've seen it at least once since then, but to be honest I can't remember if I was on master or another branch without the patch at the time.

I'm usually running Geary under gdb with glib fatal-criticals enabled, so if it happens again I'll mention it here.
Comment 5 Michael Gratton 2018-02-12 03:28:44 UTC
That commit is in Geary's repo, obvs: https://git.gnome.org/browse/geary/commit/?id=479e99465d2beed7d9d57401e00153de2ea55dca
Comment 6 Michael Gratton 2018-02-15 23:05:35 UTC
Just got one then on master, i.e. including the fixes described above. Debug output leading up to it was basically the same as above, stack trace is a bit different:

Thread 1 "geary" received signal SIGTRAP, Trace/breakpoint trap.
_g_log_abort (breakpoint=breakpoint@entry=1) at ../../../../glib/gmessages.c:554
554	../../../../glib/gmessages.c: No such file or directory.
(gdb) bt
  • #0 _g_log_abort
    at ../../../../glib/gmessages.c line 554
  • #1 g_logv
    at ../../../../glib/gmessages.c line 1362
  • #2 g_log
    at ../../../../glib/gmessages.c line 1403
  • #3 g_return_if_fail_warning
    at ../../../../glib/gmessages.c line 2702
  • #4 g_tls_output_stream_gnutls_write
    at gtlsoutputstream-gnutls.c line 69
  • #5 g_output_stream_write
    at ../../../../gio/goutputstream.c line 222
  • #6 g_output_stream_write_all
    at ../../../../gio/goutputstream.c line 281
  • #7 flush_buffer
    at ../../../../gio/gbufferedoutputstream.c line 422
  • #8 g_buffered_output_stream_flush
    at ../../../../gio/gbufferedoutputstream.c line 491
  • #9 g_output_stream_internal_close
    at ../../../../gio/goutputstream.c line 642
  • #10 g_output_stream_close
    at ../../../../gio/goutputstream.c line 723
  • #11 g_output_stream_dispose
    at ../../../../gio/goutputstream.c line 121
  • #12 g_filter_output_stream_dispose
    at ../../../../gio/gfilteroutputstream.c line 175
  • #13 g_object_unref
    at ../../../../gobject/gobject.c line 3293
  • #14 g_task_finalize
    at ../../../../gio/gtask.c line 631
  • #15 g_object_unref
    at ../../../../gobject/gobject.c line 3330
  • #16 g_source_callback_unref
    at ../../../../glib/gmain.c line 1566
  • #17 g_source_destroy_internal
    at ../../../../glib/gmain.c line 1255
  • #18 g_main_dispatch
    at ../../../../glib/gmain.c line 3172
  • #19 g_main_context_dispatch
    at ../../../../glib/gmain.c line 3813
  • #20 g_main_context_iterate
    at ../../../../glib/gmain.c line 3886
  • #21 g_main_context_iteration
    at ../../../../glib/gmain.c line 3947
  • #22 g_application_run
    at ../../../../gio/gapplication.c line 2401
  • #23 _vala_main
    at /home/mjg/Projects/GNOME/geary/src/client/application/main.vala line 33
  • #24 main
    at /home/mjg/Projects/GNOME/geary/src/client/application/main.vala line 7

Comment 7 Michael Gratton 2018-02-16 00:06:09 UTC
(In reply to Michael Catanzaro from comment #1)
> The other problem is that it's probably a bug in Geary -- or whatever is
> creating the GBufferedOutputStream -- that the GBufferedOutputStream is
> destroyed by the GTlsConnection. Michael, do you have any idea where the
> GBufferedOutputStream is coming from?

Sorry, I missed this question - I believe it's the one that is constructed after the GTlsClientConnection is constructed, and then passed to the IMAP serialiser, here: https://git.gnome.org/browse/geary/tree/src/engine/imap/transport/imap-client-connection.vala#n461

This is the only time Geary explicitly constructs an instance of GBufferedOutputStream.

Also, I'm not sure if it's relevant, but one of the first things Geary does when it hits the command timeout is to disable graceful disconnect on the underlying GTcpConnection, then proceeds to close the buffered output stream and cause the objects that wrap the GTlsClientConnection's input/output streams to be destructed. Note also that we're explicitly not closing the underlying input/output streams obtained from the TLS connection, just the connection itself.
Comment 8 Michael Catanzaro 2018-03-01 21:37:22 UTC
(In reply to Michael Gratton from comment #7)
> Also, I'm not sure if it's relevant, but one of the first things Geary does
> when it hits the command timeout is to disable graceful disconnect on the
> underlying GTcpConnection

That's probably wrong, because it will prevent GTlsConnection from gracefully closing the TLS connection.

> then proceeds to close the buffered output stream
> and cause the objects that wrap the GTlsClientConnection's input/output
> streams to be destructed. Note also that we're explicitly not closing the
> underlying input/output streams obtained from the TLS connection, just the
> connection itself.

That seems like the right order. It doesn't explain why the GBufferedOutputStream is attempting to flush its buffer on a secondary thread after the GTlsConnection has been destroyed. But these criticals need to go away: we should return a nice GError instead in this situation, not a critical.
Comment 9 Michael Catanzaro 2018-03-01 21:44:32 UTC
Created attachment 369165 [details] [review]
Input/output streams should expect to outlast their GTlsConnection

While it's not great for the GTlsConnection's GInputStream and
GOutputStream objects to outlive the GTlsConnection, it's hardly
unexpected: reffing objects is hardly disallowed. We should return nice
errors in this case instead of emitting criticals.
Comment 10 Michael Catanzaro 2018-03-01 21:47:22 UTC
(In reply to Michael Catanzaro from comment #8)
> That's probably wrong, because it will prevent GTlsConnection from
> gracefully closing the TLS connection.

And it will prevent the GBufferedOutputStream from flushing its buffer (via GTlsConnection) on close.
Comment 11 Michael Catanzaro 2018-03-01 21:48:44 UTC
(In reply to Michael Catanzaro from comment #8)
> (In reply to Michael Gratton from comment #7)
> > Also, I'm not sure if it's relevant, but one of the first things Geary does
> > when it hits the command timeout is to disable graceful disconnect on the
> > underlying GTcpConnection
> 
> That's probably wrong, because it will prevent GTlsConnection from
> gracefully closing the TLS connection.

Ignore that, and ignore my previous comment #10. I misread your comment as "one of the first things Geary does when it hits the command timeout is to perform a graceful disconnect on the underlying GTcpConnection." That's not what you wrote. ;)
Comment 12 Michael Catanzaro 2018-03-05 02:43:59 UTC
Attachment 369165 [details] pushed as e5dac2b - Input/output streams should expect to outlast their GTlsConnection
Comment 13 Philip Withnall 2018-03-05 12:44:16 UTC
Review of attachment 369165 [details] [review]:

Post-hoc review: this looks fine to me.
Comment 14 Michael Gratton 2018-03-06 02:48:24 UTC
This sounds good to me, fwiw. Cheers!