packages feed

haskell-gi-base 0.20.4 → 0.20.5

raw patch · 5 files changed

+91/−33 lines, 5 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Data.GI.Base.GVariant: instance (GHC.Classes.Eq key, GHC.Classes.Eq value) => GHC.Classes.Eq (Data.GI.Base.GVariant.GVariantDictEntry key value)
- Data.GI.Base.GVariant: instance (GHC.Show.Show key, GHC.Show.Show value) => GHC.Show.Show (Data.GI.Base.GVariant.GVariantDictEntry key value)
+ Data.GI.Base.GVariant: instance (GHC.Classes.Eq value, GHC.Classes.Eq key) => GHC.Classes.Eq (Data.GI.Base.GVariant.GVariantDictEntry key value)
+ Data.GI.Base.GVariant: instance (GHC.Show.Show value, GHC.Show.Show key) => GHC.Show.Show (Data.GI.Base.GVariant.GVariantDictEntry key value)
- Data.GI.Base.ManagedPtr: disownBoxed :: BoxedObject a => a -> IO (Ptr a)
+ Data.GI.Base.ManagedPtr: disownBoxed :: (HasCallStack, BoxedObject a) => a -> IO (Ptr a)
- Data.GI.Base.ShortPrelude: (/=) :: a -> a -> Bool
+ Data.GI.Base.ShortPrelude: (/=) :: Eq a => a -> a -> Bool
- Data.GI.Base.ShortPrelude: (==) :: a -> a -> Bool
+ Data.GI.Base.ShortPrelude: (==) :: Eq a => a -> a -> Bool
- Data.GI.Base.ShortPrelude: (>>) :: m a -> m b -> m b
+ Data.GI.Base.ShortPrelude: (>>) :: Monad m => m a -> m b -> m b
- Data.GI.Base.ShortPrelude: (>>=) :: m a -> (a -> m b) -> m b
+ Data.GI.Base.ShortPrelude: (>>=) :: Monad m => m a -> (a -> m b) -> m b
- Data.GI.Base.ShortPrelude: fail :: String -> m a
+ Data.GI.Base.ShortPrelude: fail :: Monad m => String -> m a
- Data.GI.Base.ShortPrelude: fromEnum :: a -> Int
+ Data.GI.Base.ShortPrelude: fromEnum :: Enum a => a -> Int
- Data.GI.Base.ShortPrelude: return :: a -> m a
+ Data.GI.Base.ShortPrelude: return :: Monad m => a -> m a
- Data.GI.Base.ShortPrelude: show :: a -> String
+ Data.GI.Base.ShortPrelude: show :: Show a => a -> String
- Data.GI.Base.ShortPrelude: showList :: [a] -> ShowS
+ Data.GI.Base.ShortPrelude: showList :: Show a => [a] -> ShowS
- Data.GI.Base.ShortPrelude: showsPrec :: Int -> a -> ShowS
+ Data.GI.Base.ShortPrelude: showsPrec :: Show a => Int -> a -> ShowS
- Data.GI.Base.ShortPrelude: toEnum :: Int -> a
+ Data.GI.Base.ShortPrelude: toEnum :: Enum a => Int -> a

Files

ChangeLog.md view
@@ -1,3 +1,10 @@+### 0.20.5+++ Run object finalizers in the main loop. The reason is that for+some types the destructor is not thread safe, and assumes that it+is being run from the same thread as the thread that created the object,+which can lead to crashes when using the threaded runtime.+ ### 0.20.4  + Better error diagnostics for [wrapObject](https://hackage.haskell.org/package/haskell-gi-base/docs/Data-GI-Base-ManagedPtr.html#v:wrapObject) and [newObject](https://hackage.haskell.org/package/haskell-gi-base/docs/Data-GI-Base-ManagedPtr.html#v:newObject).
Data/GI/Base/GError.hsc view
@@ -11,15 +11,15 @@ -- -- For convenience, generated code also includes specialized variants -- of 'catchGErrorJust' \/ 'handleGErrorJust' for each error type. For--- example, for errors of type 'GI.GdkPixbuf.Enums.PixbufError' one could--- invoke 'GI.GdkPixbuf.Enums.catchPixbufError' \/--- 'GI.GdkPixbuf.Enums.handlePixbufError'. The definition is simply+-- example, for errors of type <https://hackage.haskell.org/package/gi-gdkpixbuf/docs/GI-GdkPixbuf-Enums.html#t:PixbufError PixbufError> one could+-- invoke <https://hackage.haskell.org/package/gi-gdkpixbuf/docs/GI-GdkPixbuf-Enums.html#v:catchPixbufError catchPixbufError> \/+-- <https://hackage.haskell.org/package/gi-gdkpixbuf-2.0.14/docs/GI-GdkPixbuf-Enums.html#v:handlePixbufError handlePixbufError>. The definition is simply -- -- > catchPixbufError :: IO a -> (PixbufError -> GErrorMessage -> IO a) -> IO a -- > catchPixbufError = catchGErrorJustDomain -- -- Notice that the type is suitably specialized, so only--- errors of type 'GI.GdkPixbuf.Enums.PixbufError' will be caught.+-- errors of type <https://hackage.haskell.org/package/gi-gdkpixbuf/docs/GI-GdkPixbuf-Enums.html#t:PixbufError PixbufError> will be caught. module Data.GI.Base.GError     (     -- * Unpacking GError@@ -149,7 +149,7 @@ --   class. This class helps to hide the raw error and domain codes from the --   user. ----- Example for 'GI.GdkPixbuf.PixbufError':+-- Example for <https://hackage.haskell.org/package/gi-gdkpixbuf/docs/GI-GdkPixbuf-Enums.html#t:PixbufError PixbufError>: -- -- > instance GErrorClass PixbufError where -- >   gerrorClassDomain _ = "gdk-pixbuf-error-quark"
Data/GI/Base/ManagedPtr.hs view
@@ -98,9 +98,7 @@              }  -- | Do not run the finalizers upon garbage collection of the--- `ManagedPtr`, for the given reason. If later code tries to access--- the underlying pointer the given reason will be printed as part of--- the error message.+-- `ManagedPtr`. disownManagedPtr :: forall a. (HasCallStack, ManagedPtrNewtype a) => a -> IO (Ptr a) disownManagedPtr managed = do   ptr <- unsafeManagedPtrGetPtr managed@@ -250,8 +248,10 @@   fPtr <- newManagedPtr' ptr_to_g_object_unref $ castPtr ptr   return $! constructor fPtr --foreign import ccall "dbg_g_object_unref"+-- It is fine to use unsafe here, since all this does is schedule an+-- idle callback. The scheduling itself will never block for a long+-- time, or call back into Haskell.+foreign import ccall unsafe "dbg_g_object_unref"         dbg_g_object_unref :: Ptr a -> IO ()  -- | Decrease the reference count of the given 'GObject'. The memory@@ -273,7 +273,10 @@                      dbg_g_object_disown ptr                      castPtr <$> disownManagedPtr obj -foreign import ccall "boxed_free_helper" boxed_free_helper ::+-- It is fine to use unsafe here, since all this does is schedule an+-- idle callback. The scheduling itself will never block for a long+-- time, or call back into Haskell.+foreign import ccall unsafe "boxed_free_helper" boxed_free_helper ::     CGType -> Ptr a -> IO ()  foreign import ccall "g_boxed_copy" g_boxed_copy ::@@ -312,18 +315,18 @@ foreign import ccall "g_boxed_free" g_boxed_free ::     CGType -> Ptr a -> IO () --- | Free the memory associated with a boxed object+-- | Free the memory associated with a boxed object. Note that this+-- disowns the associated `ManagedPtr` via `disownManagedPtr`. freeBoxed :: forall a. (HasCallStack, BoxedObject a) => a -> IO () freeBoxed boxed = do   GType gtype <- boxedType (undefined :: a)-  ptr <- unsafeManagedPtrGetPtr boxed+  ptr <- disownManagedPtr boxed   g_boxed_free gtype ptr-  touchManagedPtr boxed  -- | Disown a boxed object, that is, do not free the associated -- foreign GBoxed when the Haskell object gets garbage -- collected. Returns the pointer to the underlying `BoxedObject`.-disownBoxed :: BoxedObject a => a -> IO (Ptr a)+disownBoxed :: (HasCallStack, BoxedObject a) => a -> IO (Ptr a) disownBoxed = disownManagedPtr  -- | Wrap a pointer, taking ownership of it.
c/hsgclosure.c view
@@ -6,6 +6,7 @@ #include <stdlib.h>  #include <glib-object.h>+#include <glib.h>  int check_object_type(void *instance, GType type) {@@ -32,27 +33,52 @@   return __print_debug_info; } -/* Auxiliary function for freeing boxed types */-void boxed_free_helper (GType gtype, void *boxed)+/* Information about a boxed type to free */+typedef struct {+  GType gtype;+  gpointer boxed;+} BoxedFreeInfo;++/* Auxiliary function for freeing boxed types in the main loop. See+   the annotation in g_object_unref_in_main_loop() below. */+static gboolean main_loop_boxed_free_helper (gpointer _info) {+  BoxedFreeInfo *info = (BoxedFreeInfo*)_info;+   if (print_debug_info()) {-    fprintf(stderr, "Freeing a boxed object at %p\n", boxed);-    fprintf(stderr, "\tIt is of type %s\n", g_type_name(gtype));+    GThread *self = g_thread_self ();++    fprintf(stderr, "Freeing a boxed object at %p from idle callback [thread: %p]\n",+            info->boxed, self);+    fprintf(stderr, "\tIt is of type %s\n", g_type_name(info->gtype));   } -  g_boxed_free (gtype, boxed);+  g_boxed_free (info->gtype, info->boxed);    if (print_debug_info()) {     fprintf(stderr, "\tdone\n");   }++  g_free(info); } +void boxed_free_helper (GType gtype, void *boxed)+{+  BoxedFreeInfo *info = g_malloc(sizeof(BoxedFreeInfo));++  info->gtype = gtype;+  info->boxed = boxed;++  g_idle_add (main_loop_boxed_free_helper, info);+}+ void dbg_g_object_disown (GObject *obj) {   GType gtype;    if (print_debug_info()) {-    fprintf(stderr, "Disowning a GObject at %p\n", obj);+    GThread *self = g_thread_self();+    fprintf(stderr, "Disowning a GObject at %p [thread: %p]\n", obj, self);     gtype = G_TYPE_FROM_INSTANCE (obj);     fprintf(stderr, "\tIt is of type %s\n", g_type_name(gtype));     fprintf(stderr, "\tIts refcount before disowning is %d\n",@@ -60,25 +86,45 @@   } } -void dbg_g_object_unref (GObject *obj)+static void print_object_dbg_info (GObject *obj) {+  GThread *self = g_thread_self();   GType gtype; +  fprintf(stderr, "Unref of %p from idle callback [thread: %p]\n", obj, self);+  gtype = G_TYPE_FROM_INSTANCE (obj);+  fprintf(stderr, "\tIt is of type %s\n", g_type_name(gtype));+  fprintf(stderr, "\tIts refcount before unref is %d\n",+          (int)obj->ref_count);+}++/*+  We schedule all GObject deletions to happen in the main loop. The+  reason is that for some types the destructor is not thread safe, and+  assumes that it is being run from the same thread as the main loop+  that created the object.+ */+static gboolean+g_object_unref_in_main_loop (gpointer obj)+{   if (print_debug_info()) {-    fprintf(stderr, "Freeing a GObject at %p\n", obj);-    gtype = G_TYPE_FROM_INSTANCE (obj);-    fprintf(stderr, "\tIt is of type %s\n", g_type_name(gtype));-    fprintf(stderr, "\tIts refcount before unref is %d\n",-            (int)obj->ref_count);+    print_object_dbg_info ((GObject*)obj);   } -  g_object_unref(obj);+  g_object_unref (obj);    if (print_debug_info()) {-    fprintf(stderr, "\tdone\n");+    fprintf(stderr, "\tUnref done\n");   }++  return FALSE; /* Do not invoke again */ } +void dbg_g_object_unref (GObject *obj)+{+  g_idle_add(g_object_unref_in_main_loop, obj);+}+ /**  * dbg_g_object_new:  * @gtype: #GType for the object to construct.@@ -98,8 +144,10 @@   gpointer result;    if (print_debug_info()) {-    fprintf(stderr, "Creating a new GObject of type %s\n",-            g_type_name(gtype));+    GThread *self = g_thread_self();++    fprintf(stderr, "Creating a new GObject of type %s [thread: %p]\n",+            g_type_name(gtype), self);   }    result = g_object_newv (gtype, n_params, params);
haskell-gi-base.cabal view
@@ -1,5 +1,5 @@ name:                haskell-gi-base-version:             0.20.4+version:             0.20.5 synopsis:            Foundation for libraries generated by haskell-gi description:         Foundation for libraries generated by haskell-gi homepage:            https://github.com/haskell-gi/haskell-gi-base@@ -43,7 +43,7 @@                        Data.GI.Base.Signals,                        Data.GI.Base.Utils -  pkgconfig-depends:   gobject-2.0 >= 2.32+  pkgconfig-depends:   gobject-2.0 >= 2.32, glib-2.0   build-depends:       base >= 4.7 && < 5,                        bytestring,                        containers,