Report all dirty objects corrupted by each sandbox crash.
authorshort <>
Fri, 12 Sep 2003 19:42:35 +0000 (19:42 +0000)
committershort <>
Fri, 12 Sep 2003 19:42:35 +0000 (19:42 +0000)
Fixed 'BROKEN' state to never reincarnate back to 'CLOSED'&'DIRTY' state.

src/libcaptive/client/parent-connector.c

index e1931ca..3de15e1 100644 (file)
@@ -27,7 +27,8 @@
 #define CAPTIVE_PARENT_CONNECTOR_CORBA_OBJECTP             "captive_parent_connector-corba_objectp"    /* &CORBA_Object */
 #define CAPTIVE_PARENT_CONNECTOR_CAPTIVE_VFS_PARENT_OBJECT "captive_parent_connector-captive_vfs_parent_object"        /* &CaptiveVfsParentObject */
 #define CAPTIVE_PARENT_CONNECTOR_DIRTY                     "captive_parent_connector-dirty"    /* GINT_TO_POINTER(0/1) */
-#define CAPTIVE_PARENT_CONNECTOR_VFS_SIGNALS_CONNECTED     "captive_parent_connector-vfs_signals_connected"    /* GINT_TO_POINTER(0/1) */
+#define CAPTIVE_PARENT_CONNECTOR_BROKEN                    "captive_parent_connector-broken"   /* GINT_TO_POINTER(0/1) */
+#define CAPTIVE_PARENT_CONNECTOR_SELF_REFS                 "captive_parent_connector-self_refs"        /* GINT_TO_POINTER(count) */
 
 
 /*
@@ -124,14 +125,15 @@ static void captive_parent_connector_vfs_detach(CaptiveVfsParentObject *captive_
 {
        g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
        g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
-       g_return_if_fail(captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
+       g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
+                       || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
 
        /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
                /* NOP */;
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
                /* NOP */;
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
-               g_assert_not_reached();
+               /* NOP */;
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
                (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->close)(captive_parent_connector);       /* errors ignored */
                g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED));
@@ -144,7 +146,8 @@ static void captive_parent_connector_vfs_cease(CaptiveVfsParentObject *captive_v
 {
        g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
        g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
-       g_return_if_fail(captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
+       g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
+                       || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
 
        /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
                /* NOP */;
@@ -166,14 +169,25 @@ static void captive_parent_connector_vfs_abort(CaptiveVfsParentObject *captive_v
 {
        g_return_if_fail(CAPTIVE_VFS_PARENT_IS_OBJECT(captive_vfs_parent_object));
        g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
-       g_return_if_fail(captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
+       g_return_if_fail(NULL==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector)
+                       || captive_vfs_parent_object==captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector));
+
+       if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY_OR_OPENED_DIRTY))
+               g_warning(_("Filesystem crash broke dirty object: %s"),
+                               (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->get_pathname)(captive_parent_connector));
 
        /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
                /* NOP */;
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
                /* NOP */;
-       else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
-               /* NOP */;      /* -> DISCONNECTED or BROKEN */
+       else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_CLEAN))
+               /* NOP */;      /* -> DISCONNECTED */
+       else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY)) {
+               /* -> BROKEN */
+               /* Ensure to never become VFS-capable Connector from BROKEN state. */
+               g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN,
+                               GINT_TO_POINTER(TRUE));
+               }
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED)) {
                (*CAPTIVE_PARENT_CONNECTOR_GET_IFACE(captive_parent_connector)->close)(captive_parent_connector);       /* errors ignored */
                g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED));
@@ -191,10 +205,8 @@ CaptiveVfsParentObject *captive_vfs_parent_object;
 
        captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
 
-       if (g_object_get_data(G_OBJECT(captive_vfs_parent_object),CAPTIVE_PARENT_CONNECTOR_VFS_SIGNALS_CONNECTED))
-               return;
-
-       g_object_ref(captive_vfs_parent_object);
+       /* Prevent multiple equivalent signal handlers. */
+       captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
 
        g_signal_connect(captive_vfs_parent_object,"detach",
                        G_CALLBACK(captive_parent_connector_vfs_detach),captive_parent_connector);      /* c_handler,data */
@@ -202,22 +214,17 @@ CaptiveVfsParentObject *captive_vfs_parent_object;
                        G_CALLBACK(captive_parent_connector_vfs_cease),captive_parent_connector);       /* c_handler,data */
        g_signal_connect(captive_vfs_parent_object,"abort",
                        G_CALLBACK(captive_parent_connector_vfs_abort),captive_parent_connector);       /* c_handler,data */
-
-       g_object_set_data(G_OBJECT(captive_vfs_parent_object),CAPTIVE_PARENT_CONNECTOR_VFS_SIGNALS_CONNECTED,
-                       GINT_TO_POINTER(TRUE));
 }
 
 static void captive_parent_connector_vfs_signals_disconnect(CaptiveParentConnector *captive_parent_connector)
 {
 CaptiveVfsParentObject *captive_vfs_parent_object;
+gint self_refs;
 
        g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
 
        captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
 
-       if (!g_object_get_data(G_OBJECT(captive_vfs_parent_object),CAPTIVE_PARENT_CONNECTOR_VFS_SIGNALS_CONNECTED))
-               return;
-
        g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
                        G_CALLBACK(captive_parent_connector_vfs_detach),captive_parent_connector);      /* func,data */
        g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
@@ -225,12 +232,24 @@ CaptiveVfsParentObject *captive_vfs_parent_object;
        g_signal_handlers_disconnect_by_func(captive_vfs_parent_object,
                        G_CALLBACK(captive_parent_connector_vfs_abort),captive_parent_connector);       /* func,data */
 
-       g_object_unref(captive_vfs_parent_object);
-
-       g_object_set_data(G_OBJECT(captive_vfs_parent_object),CAPTIVE_PARENT_CONNECTOR_VFS_SIGNALS_CONNECTED,
-                       GINT_TO_POINTER(FALSE));
+       /* Do not 'while'-cycle the loop by 1-decreasing as we cannot g_object_get_data()
+        * on fully unreffed GObject.
+        */
+       if ((self_refs=GPOINTER_TO_INT(
+                       g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS)))) {
+               g_assert(self_refs>0);
+               g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS,
+                               GINT_TO_POINTER(0));
+               while (self_refs--) {
+                       /* Undo captive_directory_close() / captive_file_close(): */
+                       g_object_ref(captive_vfs_parent_object);
+                       /* Cause g_object_last_unref(): */
+                       g_object_unref(captive_parent_connector);
+                       }
+               }
 }
 
+
 void captive_parent_connector_init(CaptiveParentConnector *captive_parent_connector,
                CORBA_Object *corba_objectp,CaptiveVfsParentObject *captive_vfs_parent_object)
 {
@@ -246,7 +265,33 @@ void captive_parent_connector_init(CaptiveParentConnector *captive_parent_connec
        g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_DIRTY,
                        GINT_TO_POINTER(FALSE));
 
-       g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_CLOSED));
+       g_assert(
+                       captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_CLOSED_CLEAN));
+}
+
+
+/* Abort dispose()? */
+gboolean captive_parent_connector_dispose(CaptiveParentConnector *captive_parent_connector)
+{
+       g_return_val_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector),FALSE);
+
+       if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY)) {
+CaptiveVfsParentObject *captive_vfs_parent_object;
+
+               captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
+
+               /* Cancel g_object_last_unref(): */
+               g_object_ref(captive_parent_connector);
+               /* Simulate captive_directory_close() / captive_file_close(): */
+               g_object_unref(captive_vfs_parent_object);
+               g_object_set_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS,
+                               GINT_TO_POINTER(1+GPOINTER_TO_INT(
+                                               g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_SELF_REFS))));
+               return TRUE;    /* abort dispose() */
+               }
+
+       captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
+       return FALSE;   /* continue dispose() */
 }
 
 
@@ -254,7 +299,10 @@ void captive_parent_connector_finalize(CaptiveParentConnector *captive_parent_co
 {
        g_return_if_fail(CAPTIVE_IS_PARENT_CONNECTOR(captive_parent_connector));
 
-       g_assert(captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_CLOSED));
+       g_assert(captive_parent_connector_is_state(
+                       captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED_OR_BROKEN_OR_CLOSED));
+       /* Should have been catched by captive_parent_connector_dispose(): */
+       g_assert(!captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED_DIRTY));
 
        captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
 }
@@ -385,14 +433,10 @@ static GnomeVFSResult captive_parent_connector_handler_close(CaptiveParentConnec
 
        /* Handler should have 'closed' us. */
 
-       /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED)) {
-               captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
+       /**/ if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_DISCONNECTED))
                return GNOME_VFS_OK;
-               }
-       else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN)) {
-               captive_parent_connector_vfs_signals_disconnect(captive_parent_connector);
+       else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_BROKEN))
                return GNOME_VFS_OK;
-               }
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_CLOSED))
                return GNOME_VFS_OK;
        else if (captive_parent_connector_is_state(captive_parent_connector,CAPTIVE_PARENT_CONNECTOR_FLAGS_OPENED))
@@ -458,13 +502,16 @@ CaptiveVfsParentObject *captive_vfs_parent_object;
 
                captive_vfs_parent_object=captive_parent_connector_get_captive_vfs_parent_object(captive_parent_connector);
                if ((vfs_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=
-                               (/* !CORBA_Object_is_nil() */ captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL))
+                               (!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
+                                               && /* !CORBA_Object_is_nil() */ captive_vfs_parent_object->corba_Vfs_object!=CORBA_OBJECT_NIL))
                        return FALSE;
                }
        if (corba_object_want!=CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ANY) {
 CORBA_Object corba_object;
 
                corba_object=captive_parent_connector_get_corba_object(captive_parent_connector);
+               g_assert(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
+                               || corba_object==CORBA_OBJECT_NIL);
                if ((corba_object_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=
                                (/* !CORBA_Object_is_nil() */ corba_object!=CORBA_OBJECT_NIL))
                        return FALSE;
@@ -473,6 +520,8 @@ CORBA_Object corba_object;
 gboolean dirty;
 
                dirty=captive_parent_connector_get_dirty(captive_parent_connector);
+               g_assert(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(captive_parent_connector),CAPTIVE_PARENT_CONNECTOR_BROKEN))
+                               || dirty==TRUE);
                if ((dirty_want==CAPTIVE_PARENT_CONNECTOR_FLAG_WANT_ON)!=dirty)
                        return FALSE;
                }