Commit 11ad437c authored by Alexander Larsson's avatar Alexander Larsson Committed by Alexander Larsson
Browse files

Always use the in-process metafile factory. We don't need it oop, since

2006-11-03  Alexander Larsson  <alexl@redhat.com>

	* libnautilus-private/nautilus-directory-metafile.c:
	Always use the in-process metafile factory. We don't need it
	oop, since nautilus is single process these days. This fixes
	some strange races with bonobo-activation that caused #351713

	* src/nautilus-application.[ch]:
	* src/nautilus-shell.h:
	Change the way we use bonobo-activation to get the NautilusShell
	so that we don't rely on bonobo-activation-server to spawn nautilus,
	as this could lead to some strange duplicate processes.
	We now directly try to register the app-wide shell object with
	bonobo-activation manually and activate it with
	Bonobo_ACTIVATION_FLAG_EXISTING_ONLY.

	* src/nautilus-shell.c:
	Handle all corba calls from the NautilusShell in an idle handler.
	This fixes some crashes where we reentered badly into e.g. quit
	when calling gconf.

	* src/nautilus-main.c:
	Since we now handle the initial open_window shell calls via an idle
	we need to delay until idle time to know if we can quit or not.
parent 01784c45
2006-11-03 Alexander Larsson <alexl@redhat.com>
* libnautilus-private/nautilus-directory-metafile.c:
Always use the in-process metafile factory. We don't need it
oop, since nautilus is single process these days. This fixes
some strange races with bonobo-activation that caused #351713
* src/nautilus-application.[ch]:
* src/nautilus-shell.h:
Change the way we use bonobo-activation to get the NautilusShell
so that we don't rely on bonobo-activation-server to spawn nautilus,
as this could lead to some strange duplicate processes.
We now directly try to register the app-wide shell object with
bonobo-activation manually and activate it with
Bonobo_ACTIVATION_FLAG_EXISTING_ONLY.
* src/nautilus-shell.c:
Handle all corba calls from the NautilusShell in an idle handler.
This fixes some crashes where we reentered badly into e.g. quit
when calling gconf.
* src/nautilus-main.c:
Since we now handle the initial open_window shell calls via an idle
we need to delay until idle time to know if we can quit or not.
2006-11-02 Alexander Larsson <alexl@redhat.com> 2006-11-02 Alexander Larsson <alexl@redhat.com>
* test/file-torture.py (main): * test/file-torture.py (main):
......
...@@ -36,7 +36,13 @@ ...@@ -36,7 +36,13 @@
#include <stdio.h> #include <stdio.h>
static Nautilus_MetafileFactory factory = CORBA_OBJECT_NIL; static Nautilus_MetafileFactory factory = CORBA_OBJECT_NIL;
static gboolean get_factory_from_oaf = TRUE; /* We disable the remote metafile factory, because there seems to be some
* sort of races with bonobo activation that sometimes leads to crashes
* like in bug #351713. This isn't really a problem anyway, since nautilus
* is only one process these days, and we still use bonobo activation to
* avoid starting multiple copies of it.
*/
static gboolean get_factory_from_oaf = FALSE;
void void
nautilus_directory_use_self_contained_metafile_factory (void) nautilus_directory_use_self_contained_metafile_factory (void)
...@@ -147,14 +153,7 @@ get_metafile (NautilusDirectory *directory) ...@@ -147,14 +153,7 @@ get_metafile (NautilusDirectory *directory)
if (directory->details->metafile_corba_object == CORBA_OBJECT_NIL) { if (directory->details->metafile_corba_object == CORBA_OBJECT_NIL) {
uri = nautilus_directory_get_uri (directory); uri = nautilus_directory_get_uri (directory);
directory->details->metafile_corba_object = open_metafile (uri, FALSE);
directory->details->metafile_corba_object = open_metafile (uri, !get_factory_from_oaf);
if (directory->details->metafile_corba_object == CORBA_OBJECT_NIL) {
g_assert (get_factory_from_oaf);
free_factory ();
directory->details->metafile_corba_object = open_metafile (uri, TRUE);
}
g_free (uri); g_free (uri);
} }
......
...@@ -172,6 +172,8 @@ nautilus_application_instance_init (NautilusApplication *application) ...@@ -172,6 +172,8 @@ nautilus_application_instance_init (NautilusApplication *application)
/* Create an undo manager */ /* Create an undo manager */
application->undo_manager = nautilus_undo_manager_new (); application->undo_manager = nautilus_undo_manager_new ();
application->shell = nautilus_shell_new (application);
/* Watch for volume mounts so we can restore open windows /* Watch for volume mounts so we can restore open windows
* This used to be for showing new window on mount, but is not * This used to be for showing new window on mount, but is not
* used anymore */ * used anymore */
...@@ -226,6 +228,11 @@ nautilus_application_destroy (BonoboObject *object) ...@@ -226,6 +228,11 @@ nautilus_application_destroy (BonoboObject *object)
g_object_unref (application->undo_manager); g_object_unref (application->undo_manager);
if (application->shell_registered) {
bonobo_activation_unregister_active_server (SHELL_IID, BONOBO_OBJREF (application->shell));
}
bonobo_object_unref (application->shell);
EEL_CALL_PARENT (BONOBO_OBJECT_CLASS, destroy, (object)); EEL_CALL_PARENT (BONOBO_OBJECT_CLASS, destroy, (object));
} }
...@@ -517,12 +524,16 @@ nautilus_application_startup (NautilusApplication *application, ...@@ -517,12 +524,16 @@ nautilus_application_startup (NautilusApplication *application,
while (TRUE) { while (TRUE) {
/* Try to register the file manager view factory. */ /* Try to register the file manager view factory. */
result = nautilus_bonobo_activation_register_for_display result = nautilus_bonobo_activation_register_for_display
(FACTORY_IID, BONOBO_OBJREF (application)); (SHELL_IID, BONOBO_OBJREF (application->shell));
switch (result) { switch (result) {
case Bonobo_ACTIVATION_REG_SUCCESS: case Bonobo_ACTIVATION_REG_SUCCESS:
/* We are registered and all is right with the world. */ /* We are registered and all is right with the world. */
application->shell_registered = TRUE;
finish_startup (application); finish_startup (application);
message = NULL;
detailed_message = NULL;
break;
case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE: case Bonobo_ACTIVATION_REG_ALREADY_ACTIVE:
/* Another copy of nautilus already is running and registered. */ /* Another copy of nautilus already is running and registered. */
message = NULL; message = NULL;
...@@ -583,7 +594,7 @@ nautilus_application_startup (NautilusApplication *application, ...@@ -583,7 +594,7 @@ nautilus_application_startup (NautilusApplication *application,
/* Get the shell object. */ /* Get the shell object. */
if (message == NULL) { if (message == NULL) {
shell = bonobo_activation_activate_from_id (SHELL_IID, 0, NULL, NULL); shell = bonobo_activation_activate_from_id (SHELL_IID, Bonobo_ACTIVATION_FLAG_EXISTING_ONLY, NULL, NULL);
if (!CORBA_Object_is_nil (shell, &ev)) { if (!CORBA_Object_is_nil (shell, &ev)) {
break; break;
} }
...@@ -667,16 +678,6 @@ nautilus_application_startup (NautilusApplication *application, ...@@ -667,16 +678,6 @@ nautilus_application_startup (NautilusApplication *application,
init_session (); init_session ();
} }
/* We're done with the shell now, so let it go. */
/* HACK: Don't bother releasing the shell in the case where we
* just told it to quit -- that just leads to hangs and does
* no good. We could probably fix this in some fancier way if
* we could figure out a better lifetime rule.
*/
if (!(kill_shell || restart_shell)) {
bonobo_object_release_unref (shell, NULL);
}
out: out:
CORBA_exception_free (&ev); CORBA_exception_free (&ev);
} }
......
...@@ -49,9 +49,13 @@ typedef struct NautilusWindow NautilusWindow; ...@@ -49,9 +49,13 @@ typedef struct NautilusWindow NautilusWindow;
typedef struct _NautilusSpatialWindow NautilusSpatialWindow; typedef struct _NautilusSpatialWindow NautilusSpatialWindow;
#endif #endif
typedef struct NautilusShell NautilusShell;
typedef struct { typedef struct {
BonoboGenericFactory parent; BonoboGenericFactory parent;
NautilusUndoManager *undo_manager; NautilusUndoManager *undo_manager;
NautilusShell *shell;
gboolean shell_registered;
} NautilusApplication; } NautilusApplication;
typedef struct { typedef struct {
......
...@@ -108,6 +108,15 @@ event_loop_unregister (GtkObject *object) ...@@ -108,6 +108,15 @@ event_loop_unregister (GtkObject *object)
} }
} }
static gboolean
initial_event_loop_needed (gpointer data)
{
if (!is_event_loop_needed ()) {
eel_gtk_main_quit_all ();
}
return FALSE;
}
void void
nautilus_main_event_loop_register (GtkObject *object) nautilus_main_event_loop_register (GtkObject *object)
{ {
...@@ -367,9 +376,11 @@ main (int argc, char *argv[]) ...@@ -367,9 +376,11 @@ main (int argc, char *argv[])
remaining); remaining);
g_free (startup_id_copy); g_free (startup_id_copy);
if (is_event_loop_needed ()) { /* The application startup does things in an idle, so
gtk_main (); we need to check whether the main loop is needed in an idle
} */
g_idle_add (initial_event_loop_needed, NULL);
gtk_main ();
} }
/* This has to be done before gnome_vfs_shutdown, because /* This has to be done before gnome_vfs_shutdown, because
......
...@@ -171,6 +171,44 @@ open_window (NautilusShell *shell, const char *uri, const char *startup_id, ...@@ -171,6 +171,44 @@ open_window (NautilusShell *shell, const char *uri, const char *startup_id,
} }
} }
typedef struct {
NautilusShell *shell;
char *startup_id;
char *geometry;
GList *uris;
gboolean browser_window;
} OpenWindowData;
static gboolean
open_windows_at_idle (gpointer _data)
{
OpenWindowData *data = _data;
char *uri;
GList *l;
if (data->uris == NULL) {
if (!restore_window_states (data->shell)) {
/* Open a window pointing at the default location. */
open_window (data->shell, NULL, data->startup_id,
data->geometry, data->browser_window);
}
} else {
/* Open windows at each requested location. */
for (l = data->uris; l != NULL; l = l->next) {
uri = (char *)l->data;
open_window (data->shell, uri, data->startup_id,
data->geometry, data->browser_window);
g_free (uri);
}
}
g_free (data->startup_id);
g_free (data->geometry);
g_list_free (data->uris);
g_free (data);
return FALSE;
}
static void static void
corba_open_windows (PortableServer_Servant servant, corba_open_windows (PortableServer_Servant servant,
const Nautilus_URIList *list, const Nautilus_URIList *list,
...@@ -179,16 +217,25 @@ corba_open_windows (PortableServer_Servant servant, ...@@ -179,16 +217,25 @@ corba_open_windows (PortableServer_Servant servant,
CORBA_boolean browser_window, CORBA_boolean browser_window,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
NautilusShell *shell; OpenWindowData *data;
guint i; guint i;
shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant)); data = g_new0 (OpenWindowData, 1);
data->shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
data->startup_id = g_strdup (startup_id);
data->geometry = g_strdup (geometry);
data->browser_window = browser_window;
/* Open windows at each requested location. */
for (i = 0; i < list->_length; i++) { for (i = 0; i < list->_length; i++) {
g_assert (list->_buffer[i] != NULL); g_assert (list->_buffer[i] != NULL);
open_window (shell, list->_buffer[i], startup_id, geometry, browser_window); data->uris = g_list_prepend (data->uris,
g_strdup (list->_buffer[i]));
} }
data->uris = g_list_reverse (data->uris);
g_idle_add (open_windows_at_idle, data);
} }
static void static void
...@@ -198,14 +245,35 @@ corba_open_default_window (PortableServer_Servant servant, ...@@ -198,14 +245,35 @@ corba_open_default_window (PortableServer_Servant servant,
CORBA_boolean browser_window, CORBA_boolean browser_window,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
OpenWindowData *data;
data = g_new0 (OpenWindowData, 1);
data->shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
data->startup_id = g_strdup (startup_id);
data->geometry = g_strdup (geometry);
data->browser_window = browser_window;
g_idle_add (open_windows_at_idle, data);
}
typedef struct {
NautilusShell *shell; NautilusShell *shell;
char *filename;
} LoadSessionData;
shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant)); static gboolean
load_session_at_idle (gpointer _data)
{
NautilusApplication *application;
LoadSessionData *data = _data;
if (!restore_window_states (shell)) { application = NAUTILUS_APPLICATION (data->shell->details->application);
/* Open a window pointing at the default location. */ nautilus_application_load_session (application, data->filename);
open_window (shell, NULL, startup_id, geometry, browser_window);
} g_free (data->filename);
g_free (data);
return FALSE;
} }
static void static void
...@@ -213,40 +281,72 @@ corba_load_session (PortableServer_Servant servant, ...@@ -213,40 +281,72 @@ corba_load_session (PortableServer_Servant servant,
const CORBA_char *filename, const CORBA_char *filename,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
NautilusShell *shell; LoadSessionData *data;
NautilusApplication *application;
data = g_new0 (LoadSessionData, 1);
data->shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
data->filename = g_strdup (filename);
g_idle_add (load_session_at_idle, data);
}
typedef struct {
NautilusShell *shell;
} StartDesktopData;
static gboolean
start_desktop_at_idle (gpointer _data)
{
StartDesktopData *data = _data;
NautilusApplication *application;
shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant)); application = NAUTILUS_APPLICATION (data->shell->details->application);
application = NAUTILUS_APPLICATION (shell->details->application); nautilus_application_open_desktop (application);
nautilus_application_load_session (application, filename); g_free (data);
return FALSE;
} }
static void static void
corba_start_desktop (PortableServer_Servant servant, corba_start_desktop (PortableServer_Servant servant,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
NautilusShell *shell; StartDesktopData *data;
NautilusApplication *application;
shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
application = NAUTILUS_APPLICATION (shell->details->application);
nautilus_application_open_desktop (application); data = g_new0 (StartDesktopData, 1);
data->shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
g_idle_add (start_desktop_at_idle, data);
}
static gboolean
stop_desktop_at_idle (gpointer data)
{
nautilus_application_close_desktop ();
return FALSE;
} }
static void static void
corba_stop_desktop (PortableServer_Servant servant, corba_stop_desktop (PortableServer_Servant servant,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
nautilus_application_close_desktop (); g_idle_add (stop_desktop_at_idle, NULL);
} }
static gboolean
quit_at_idle (gpointer data)
{
nautilus_main_event_loop_quit ();
return FALSE;
}
static void static void
corba_quit (PortableServer_Servant servant, corba_quit (PortableServer_Servant servant,
CORBA_Environment *ev) CORBA_Environment *ev)
{ {
nautilus_main_event_loop_quit (); g_idle_add (quit_at_idle, NULL);
} }
/* /*
...@@ -403,12 +503,19 @@ restore_window_states (NautilusShell *shell) ...@@ -403,12 +503,19 @@ restore_window_states (NautilusShell *shell)
return result; return result;
} }
static void static gboolean
corba_restart (PortableServer_Servant servant, restart_at_idle (gpointer data)
CORBA_Environment *ev)
{ {
save_window_states (); save_window_states ();
nautilus_main_event_loop_quit (); nautilus_main_event_loop_quit ();
g_setenv ("_NAUTILUS_RESTART", "yes", 1); g_setenv ("_NAUTILUS_RESTART", "yes", 1);
return FALSE;
}
static void
corba_restart (PortableServer_Servant servant,
CORBA_Environment *ev)
{
g_idle_add (restart_at_idle, NULL);
} }
...@@ -39,10 +39,10 @@ ...@@ -39,10 +39,10 @@
typedef struct NautilusShellDetails NautilusShellDetails; typedef struct NautilusShellDetails NautilusShellDetails;
typedef struct { struct NautilusShell {
BonoboObject parent_slot; BonoboObject parent_slot;
NautilusShellDetails *details; NautilusShellDetails *details;
} NautilusShell; };
typedef struct { typedef struct {
BonoboObjectClass parent_slot; BonoboObjectClass parent_slot;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment