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 391907 - Glib::Error::throw_exception() doesn't return Glib::Error instance in --disable-api-exceptions mode
Glib::Error::throw_exception() doesn't return Glib::Error instance in --disab...
Status: RESOLVED FIXED
Product: glibmm
Classification: Bindings
Component: general
2.10.x
Other All
: Normal critical
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2007-01-02 14:57 UTC by Matt Hoosier
Modified: 2007-01-06 19:53 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Matt Hoosier 2007-01-02 14:57:16 UTC
Steps to reproduce:
1. Compile this program with debugging info

#include <gdkmm/pixbuf.h>
#include <gtkmm/main.h>
#include <glib/gmessages.h>

int
main (int argc, char* argv[])
{
    Gtk::Main loop (argc, argv);

    GError* gerror = 0;
    Glib::RefPtr<Gdk::Pixbuf> pb = Glib::wrap (gdk_pixbuf_new_from_file ("/tmp/nosuch", &gerror));

    if (gerror)
    {
      printf ("%s:%d: Error: %s\n", __FILE__, __LINE__, gerror->message);
      std::auto_ptr<Glib::Error> e (::Glib::Error::throw_exception (gerror));

      // Never reached
      g_assert_not_reached ();
    }
    else
    {
        printf ("%s:%d: No error\n", __FILE__, __LINE__);
    }

    return 1;
}


2. Break on main.cc:19
3. Observe nonsensical output:

main.cc:15: Error: Failed to open file '/tmp/nosuch': No such file or directory
main.cc:23: No error

Stack trace:
There isn't a stack trace at the point of failure; the program just jumps into the wrong logic paths and crashes later because error-throwing operations appear to have succeeded.

Other information:
This code is basically lifted from the sources to Gdk::Pixbuf::create_from_file(), for the purposes of instrumenting it with debugging output.

Apologies for using the Pixbuf C++ binding type from gtkmm as a demonstration of the bug. I didn't find any operations which ought to provoke the same Glib::FileError instance in the core glibmm API itself.

At any rate, I don't think that the Gdk::Pixbuf code is at issue here; I can witness the Glib::FileError::throw_func() call return and produce the expected instance of Glib::FileError. The strangeness begins when Glib::Error::throw_exception() attempts to return that auto_ptr to the calling code (here, main.cc:16.
Comment 1 Matt Hoosier 2007-01-06 00:04:29 UTC
It turns out that this is behavior is caused by a (mis)optimization that GCC performs due to the stray "__noreturn__" annotation on Glib::Error::throw_exception(), in error.h:

  #ifdef GLIBMM_EXCEPTIONS_ENABLED
    static void throw_exception(GError* gobject) G_GNUC_NORETURN;
  #else
    static std::auto_ptr<Glib::Error> throw_exception(GError* gobject)
    G_GNUC_NORETURN;
  #endif //GLIBMM_EXCEPTIONS_ENABLED

It is mistakenly assumed that control never returns to the sites which call this function with !GLIBMM_EXCEPTIONS_ENABLED, so the "jump" instructions which prevent the "then" clause from falling down into the "else" clause, are just omitted.

This was already fixed in the 2.10.9 release, so I guess all that's left is for me to point out that the issue is more serious than the ChangeLog entry which said that removing the annotation avoided some compiler warnings. :)
Comment 2 Daniel Elstner 2007-01-06 19:53:56 UTC
OK, I'm closing this bug since it is already fixed.

By the way, it's not a "(mis)optimization" of GCC but most definitely an error in glibmm.  The fact that you hit this bug shows that the optimization is working :) Note that the noreturn attribute makes GCC optimize at the caller site, so it really can't just ignore the attribute if the function does return, since it doesn't know the definition.  But there's definitely a warning when compiling the function itself; I wonder why noone has seen that earlier.