don't save a file here, only in response to SaveYourself. Change the code

2002-03-13  Havoc Pennington  <hp@pobox.com>

	* src/session.c (meta_session_init): don't save a file here, only
	in response to SaveYourself. Change the code to properly use a
	unique state file for each SaveYourself. Totally, totally
	untested.
This commit is contained in:
Havoc Pennington 2002-03-14 04:09:42 +00:00 committed by Havoc Pennington
parent 9b86849068
commit 9e2cfcd699
4 changed files with 145 additions and 79 deletions

View File

@ -1,3 +1,10 @@
2002-03-13 Havoc Pennington <hp@pobox.com>
* src/session.c (meta_session_init): don't save a file here, only
in response to SaveYourself. Change the code to properly use a
unique state file for each SaveYourself. Totally, totally
untested.
2002-03-12 Havoc Pennington <hp@pobox.com> 2002-03-12 Havoc Pennington <hp@pobox.com>
* src/theme-viewer.c: improve the theme viewer so people * src/theme-viewer.c: improve the theme viewer so people

View File

@ -58,7 +58,7 @@ log_handler (const gchar *log_domain,
static void static void
usage (void) usage (void)
{ {
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n"); g_print ("metacity [--disable-sm] [--sm-save-file=FILENAME] [--display=DISPLAY]\n");
exit (1); exit (1);
} }
@ -72,6 +72,7 @@ main (int argc, char **argv)
const char *client_id; const char *client_id;
gboolean disable_sm; gboolean disable_sm;
const char *prev_arg; const char *prev_arg;
const char *save_file;
sigemptyset (&empty_mask); sigemptyset (&empty_mask);
act.sa_handler = SIG_IGN; act.sa_handler = SIG_IGN;
@ -100,6 +101,7 @@ main (int argc, char **argv)
display_name = NULL; display_name = NULL;
client_id = NULL; client_id = NULL;
save_file = NULL;
disable_sm = FALSE; disable_sm = FALSE;
prev_arg = NULL; prev_arg = NULL;
i = 1; i = 1;
@ -136,27 +138,27 @@ main (int argc, char **argv)
} }
else if (strcmp (arg, "--display") == 0) else if (strcmp (arg, "--display") == 0)
; /* wait for next arg */ ; /* wait for next arg */
else if (strstr (arg, "--sm-client-id=") == arg) else if (strstr (arg, "--sm-save-file=") == arg)
{ {
const char *id; const char *file;
if (client_id) if (save_file)
meta_fatal ("Can't specify client ID twice\n"); meta_fatal ("Can't specify SM save file twice\n");
id = strchr (arg, '='); file = strchr (arg, '=');
++id; ++file;
client_id = g_strdup (id); save_file = g_strdup (file);
} }
else if (prev_arg && else if (prev_arg &&
strcmp (prev_arg, "--sm-client-id") == 0) strcmp (prev_arg, "--sm-save-file") == 0)
{ {
if (client_id) if (save_file)
meta_fatal ("Can't specify client ID twice\n"); meta_fatal ("Can't specify SM save file twice\n");
client_id = g_strdup (arg); save_file = g_strdup (arg);
} }
else if (strcmp (arg, "--sm-client-id") == 0) else if (strcmp (arg, "--sm-save-file") == 0)
; /* wait for next arg */ ; /* wait for next arg */
else else
usage (); usage ();
@ -241,7 +243,7 @@ main (int argc, char **argv)
* info * info
*/ */
if (!disable_sm) if (!disable_sm)
meta_session_init (client_id); /* client_id == NULL is fine */ meta_session_init (save_file);
if (!meta_display_open (NULL)) if (!meta_display_open (NULL))
meta_exit (META_EXIT_ERROR); meta_exit (META_EXIT_ERROR);

View File

@ -17,15 +17,18 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. */ * 02111-1307, USA.
*/
#include <config.h> #include <config.h>
#include "session.h" #include "session.h"
#include <time.h>
#ifndef HAVE_SM #ifndef HAVE_SM
void void
meta_session_init (const char *previous_id) meta_session_init (const char *save_file)
{ {
meta_topic (META_DEBUG_SM, "Compiled without session management support\n"); meta_topic (META_DEBUG_SM, "Compiled without session management support\n");
} }
@ -64,8 +67,12 @@ static void ice_io_error_handler (IceConn connection);
static void new_ice_connection (IceConn connection, IcePointer client_data, static void new_ice_connection (IceConn connection, IcePointer client_data,
Bool opening, IcePointer *watch_data); Bool opening, IcePointer *watch_data);
static void save_state (void); static void save_state (void);
static void load_state (const char *previous_id); static void load_state (const char *previous_save_file);
static const char* get_previous_id (void);
static void regenerate_save_file (void);
static const char* full_save_file (void);
static const char* base_save_file (void);
/* This is called when data is available on an ICE connection. */ /* This is called when data is available on an ICE connection. */
static gboolean static gboolean
@ -196,29 +203,38 @@ static void save_yourself_callback (SmcConn smc_conn,
Bool fast); Bool fast);
static void set_clone_restart_commands (void); static void set_clone_restart_commands (void);
static gchar *client_id = NULL; static char *client_id = NULL;
static gpointer session_connection = NULL; static gpointer session_connection = NULL;
static ClientState current_state = STATE_DISCONNECTED; static ClientState current_state = STATE_DISCONNECTED;
void void
meta_session_init (const char *previous_id) meta_session_init (const char *previous_save_file)
{ {
/* Some code here from twm */ /* Some code here from twm */
char buf[256]; char buf[256];
unsigned long mask; unsigned long mask;
SmcCallbacks callbacks; SmcCallbacks callbacks;
const char *previous_id;
meta_topic (META_DEBUG_SM, "Initializing session with session ID '%s'\n", meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'\n",
previous_id ? previous_id : "(none)"); previous_save_file ? previous_save_file : "(none)");
if (previous_id) if (previous_save_file)
load_state (previous_id); load_state (previous_save_file);
previous_id = get_previous_id (); /* from the file if any, null otherwise */
ice_init (); ice_init ();
mask = SmcSaveYourselfProcMask | SmcDieProcMask | mask = SmcSaveYourselfProcMask | SmcDieProcMask |
SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
#if 0
/* note this isn't in the mask above */
callbacks.interact.callback = interact_callback;
callbacks.interact.client_data = NULL;
#endif
callbacks.save_yourself.callback = save_yourself_callback; callbacks.save_yourself.callback = save_yourself_callback;
callbacks.save_yourself.client_data = NULL; callbacks.save_yourself.client_data = NULL;
@ -238,7 +254,7 @@ meta_session_init (const char *previous_id)
SmProtoMinor, SmProtoMinor,
mask, mask,
&callbacks, &callbacks,
previous_id, (char*) previous_id,
&client_id, &client_id,
255, buf); 255, buf);
@ -280,7 +296,7 @@ meta_session_init (const char *previous_id)
prop2.type = SmARRAY8; prop2.type = SmARRAY8;
prop2.num_vals = 1; prop2.num_vals = 1;
prop2.vals = &prop2val; prop2.vals = &prop2val;
prop2val.value = g_get_user_name (); prop2val.value = (char*) g_get_user_name ();
prop2val.length = strlen (prop2val.value); prop2val.length = strlen (prop2val.value);
prop3.name = SmRestartStyleHint; prop3.name = SmRestartStyleHint;
@ -303,7 +319,7 @@ meta_session_init (const char *previous_id)
prop5.type = SmARRAY8; prop5.type = SmARRAY8;
prop5.num_vals = 1; prop5.num_vals = 1;
prop5.vals = &prop5val; prop5.vals = &prop5val;
prop5val.value = g_get_home_dir (); prop5val.value = (char*) g_get_home_dir ();
prop5val.length = strlen (prop5val.value); prop5val.length = strlen (prop5val.value);
prop6.name = "_GSM_Priority"; prop6.name = "_GSM_Priority";
@ -322,8 +338,6 @@ meta_session_init (const char *previous_id)
SmcSetProperties (session_connection, 6, props); SmcSetProperties (session_connection, 6, props);
} }
set_clone_restart_commands ();
} }
static void static void
@ -392,30 +406,12 @@ save_yourself_callback (SmcConn smc_conn,
/* The first SaveYourself after registering for the first time /* The first SaveYourself after registering for the first time
* is a special case (SM specs 7.2). * is a special case (SM specs 7.2).
*
* This SaveYourself seems to be included in the protocol to
* ask the client to specify its initial SmProperties since
* there is little point saving a copy of the initial state.
*
* A bug in xsm means that it does not send us a SaveComplete
* in response to this initial SaveYourself. Therefore, we
* must not set a grab because it would never be released.
* Indeed, even telling the app that this SaveYourself has
* arrived is hazardous as the app may take its own steps
* to freeze its WM state while waiting for the SaveComplete.
*
* Fortunately, we have already set the SmProperties during
* gnome_client_connect so there is little lost in simply
* returning immediately.
*
* Apps which really want to save their initial states can
* do so safely using gnome_client_save_yourself_request.
*/ */
#if 0 /* I think the GnomeClient rationale for this doesn't apply */
if (current_state == STATE_REGISTERING) if (current_state == STATE_REGISTERING)
{ {
current_state = STATE_IDLE; current_state = STATE_IDLE;
/* Double check that this is a section 7.2 SaveYourself: */ /* Double check that this is a section 7.2 SaveYourself: */
if (save_style == SmSaveLocal && if (save_style == SmSaveLocal &&
@ -427,9 +423,12 @@ save_yourself_callback (SmcConn smc_conn,
return; return;
} }
} }
#endif
current_state = STATE_SAVING_PHASE_1; current_state = STATE_SAVING_PHASE_1;
regenerate_save_file ();
set_clone_restart_commands (); set_clone_restart_commands ();
save_yourself_possibly_done (shutdown, successful); save_yourself_possibly_done (shutdown, successful);
@ -470,12 +469,6 @@ set_clone_restart_commands (void)
char *discardv[10]; char *discardv[10];
int i; int i;
SmProp prop1, prop2, prop3, *props[3]; SmProp prop1, prop2, prop3, *props[3];
char *session_file;
session_file = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/",
client_id,
NULL);
/* Restart (use same client ID) */ /* Restart (use same client ID) */
@ -485,9 +478,9 @@ set_clone_restart_commands (void)
i = 0; i = 0;
restartv[i] = "metacity"; restartv[i] = "metacity";
++i; ++i;
restartv[i] = "--sm-client-id"; restartv[i] = "--sm-save-file";
++i; ++i;
restartv[i] = client_id; restartv[i] = (char*) base_save_file ();
++i; ++i;
restartv[i] = NULL; restartv[i] = NULL;
@ -528,7 +521,7 @@ set_clone_restart_commands (void)
++i; ++i;
discardv[i] = "-f"; discardv[i] = "-f";
++i; ++i;
discardv[i] = session_file; discardv[i] = (char*) full_save_file ();
prop3.name = SmCloneCommand; prop3.name = SmCloneCommand;
prop3.type = SmLISTofARRAY8; prop3.type = SmLISTofARRAY8;
@ -553,8 +546,6 @@ set_clone_restart_commands (void)
g_free (prop1.vals); g_free (prop1.vals);
g_free (prop2.vals); g_free (prop2.vals);
g_free (prop3.vals); g_free (prop3.vals);
g_free (session_file);
} }
/* The remaining code in this file actually loads/saves the session, /* The remaining code in this file actually loads/saves the session,
@ -743,7 +734,6 @@ save_state (void)
{ {
char *metacity_dir; char *metacity_dir;
char *session_dir; char *session_dir;
char *session_file;
FILE *outfile; FILE *outfile;
GSList *displays; GSList *displays;
GSList *display_iter; GSList *display_iter;
@ -758,12 +748,6 @@ save_state (void)
session_dir = g_strconcat (metacity_dir, "/sessions", session_dir = g_strconcat (metacity_dir, "/sessions",
NULL); NULL);
/* Assuming client ID is a workable filename. */
session_file = g_strconcat (session_dir, "/",
client_id,
NULL);
if (mkdir (metacity_dir, 0700) < 0 && if (mkdir (metacity_dir, 0700) < 0 &&
errno != EEXIST) errno != EEXIST)
{ {
@ -778,14 +762,14 @@ save_state (void)
session_dir, g_strerror (errno)); session_dir, g_strerror (errno));
} }
meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", session_file); meta_topic (META_DEBUG_SM, "Saving session to '%s'\n", full_save_file ());
outfile = fopen (session_file, "w"); outfile = fopen (full_save_file (), "w");
if (outfile == NULL) if (outfile == NULL)
{ {
meta_warning (_("Could not open session file '%s' for writing: %s\n"), meta_warning (_("Could not open session file '%s' for writing: %s\n"),
session_file, g_strerror (errno)); full_save_file (), g_strerror (errno));
goto out; goto out;
} }
@ -917,18 +901,17 @@ save_state (void)
if (ferror (outfile)) if (ferror (outfile))
{ {
meta_warning (_("Error writing session file '%s': %s\n"), meta_warning (_("Error writing session file '%s': %s\n"),
session_file, g_strerror (errno)); full_save_file (), g_strerror (errno));
} }
if (fclose (outfile)) if (fclose (outfile))
{ {
meta_warning (_("Error closing session file '%s': %s\n"), meta_warning (_("Error closing session file '%s': %s\n"),
session_file, g_strerror (errno)); full_save_file (), g_strerror (errno));
} }
} }
g_free (metacity_dir); g_free (metacity_dir);
g_free (session_dir); g_free (session_dir);
g_free (session_file);
} }
typedef enum typedef enum
@ -973,9 +956,10 @@ static GMarkupParser metacity_session_parser = {
}; };
static GSList *window_info_list = NULL; static GSList *window_info_list = NULL;
static char* previous_id = NULL;
static void static void
load_state (const char *previous_id) load_state (const char *previous_save_file)
{ {
GMarkupParseContext *context; GMarkupParseContext *context;
GError *error; GError *error;
@ -986,7 +970,7 @@ load_state (const char *previous_id)
session_file = g_strconcat (g_get_home_dir (), session_file = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/", "/.metacity/sessions/",
previous_id, previous_save_file,
NULL); NULL);
error = NULL; error = NULL;
@ -1056,7 +1040,43 @@ start_element_handler (GMarkupParseContext *context,
if (strcmp (element_name, "metacity_session") == 0) if (strcmp (element_name, "metacity_session") == 0)
{ {
/* do nothing */ /* Get previous ID */
int i;
i = 0;
while (attribute_names[i])
{
const char *name;
const char *val;
name = attribute_names[i];
val = attribute_values[i];
if (previous_id)
{
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<metacity_session> attribute seen but we already have the session ID"));
return;
}
if (strcmp (name, "id") == 0)
{
previous_id = decode_text_from_utf8 (val);
}
else
{
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <metacity_session> element"),
name);
return;
}
++i;
}
} }
else if (strcmp (element_name, "window") == 0) else if (strcmp (element_name, "window") == 0)
{ {
@ -1277,6 +1297,11 @@ text_handler (GMarkupParseContext *context,
*/ */
} }
static const char*
get_previous_id (void)
{
return previous_id;
}
static gboolean static gboolean
both_null_or_matching (const char *a, both_null_or_matching (const char *a,
@ -1360,7 +1385,7 @@ get_possible_matches (MetaWindow *window)
return retval; return retval;
} }
const MetaWindowSessionInfo* static const MetaWindowSessionInfo*
find_best_match (GSList *infos, find_best_match (GSList *infos,
MetaWindow *window) MetaWindow *window)
{ {
@ -1478,4 +1503,36 @@ session_info_new (void)
return info; return info;
} }
static char* relative_save_path = NULL;
static char* full_save_path = NULL;
static void
regenerate_save_file (void)
{
g_free (relative_save_path);
g_free (full_save_path);
relative_save_path = g_strdup_printf ("%d-%d-%u.ms",
(int) time (NULL),
(int) getpid (),
g_random_int ());
full_save_path = g_strconcat (g_get_home_dir (),
"/.metacity/sessions/",
relative_save_path,
NULL);
}
static const char*
full_save_file (void)
{
return full_save_path;
}
static const char*
base_save_file (void)
{
return relative_save_path;
}
#endif /* HAVE_SM */ #endif /* HAVE_SM */

View File

@ -60,7 +60,7 @@ struct _MetaWindowSessionInfo
const MetaWindowSessionInfo* meta_window_lookup_saved_state (MetaWindow *window); const MetaWindowSessionInfo* meta_window_lookup_saved_state (MetaWindow *window);
void meta_window_release_saved_state (const MetaWindowSessionInfo *info); void meta_window_release_saved_state (const MetaWindowSessionInfo *info);
void meta_session_init (const char *previous_id); void meta_session_init (const char *save_file);
#endif #endif