Browse Source

* Adjust the signal io pipe implementation to be basically the same as the one Brian did for xfce-mcs-manager.

* Cosmetic changes.

(Old svn revision: 25861)
upstream/xfce4-panel-4.10.1
Jasper Huijsmans 16 years ago
parent
commit
d61ce445c5
  1. 28
      panel/main.c
  2. 280
      panel/panel-app.c
  3. 20
      panel/panel-app.h
  4. 14
      panel/panel-config.c

28
panel/main.c

@ -57,13 +57,14 @@ static gchar *opt_client_id = NULL;
/* command line options */
static GOptionEntry option_entries[] =
{
{ "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_ ("Show this message and exit"), NULL },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &opt_version, N_ ("Show this message and exit"), NULL },
{ "customize", 'c', 0, G_OPTION_ARG_NONE, &opt_customize, N_ ("Show configuration dialog"), NULL },
{ "save", 's', 0, G_OPTION_ARG_NONE, &opt_save, N_ ("Save configuration"), NULL },
{ "restart", 'r', 0, G_OPTION_ARG_NONE, &opt_restart, N_ ("Restart panels"), NULL },
{ "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_ ("End the session"), NULL },
{ "exit", 'x', 0, G_OPTION_ARG_NONE, &opt_exit, N_ ("Close all panels and end the program"), NULL },
{ "add", 'a', 0, G_OPTION_ARG_NONE, &opt_add, N_ ("Add new items"), NULL },
{ "save", 's', 0, G_OPTION_ARG_NONE, &opt_save, N_ ("Save configuration"), NULL },
{ "restart", 'r', 0, G_OPTION_ARG_NONE, &opt_restart, N_ ("Restart panels"), NULL },
{ "quit", 'q', 0, G_OPTION_ARG_NONE, &opt_quit, N_ ("End the session"), NULL },
{ "exit", 'x', 0, G_OPTION_ARG_NONE, &opt_exit, N_ ("Close all panels and end the program"), NULL },
{ "add", 'a', 0, G_OPTION_ARG_NONE, &opt_add, N_ ("Add new items"), NULL },
{ "sm-client-id", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_client_id, NULL, NULL },
{ NULL }
};
@ -81,7 +82,7 @@ main (gint argc, gchar **argv)
/* application name */
g_set_application_name (PACKAGE_NAME);
TIMER_ELAPSED ("start gtk_init_with_args ()");
MARK ("start gtk_init_with_args ()");
/* initialize gtk */
if (!gtk_init_with_args (&argc, &argv, "", option_entries, GETTEXT_PACKAGE, &error))
@ -135,30 +136,31 @@ main (gint argc, gchar **argv)
}
}
TIMER_ELAPSED ("start panel_init()");
MARK ("start panel_init()");
msg = panel_app_init ();
if (G_UNLIKELY (msg == -1))
if (G_UNLIKELY (msg == INIT_FAILURE))
{
return EXIT_FAILURE;
}
else if (G_UNLIKELY (msg == 1))
else if (G_UNLIKELY (msg == INIT_RUNNING))
{
g_message (_("xfce4-panel already running"));
return EXIT_SUCCESS;
}
TIMER_ELAPSED ("start panel_app_run()");
MARK ("start panel_app_run()");
msg = panel_app_run (opt_client_id);
MARK ("end panel_app_run()");
if (G_UNLIKELY (msg == 1))
if (G_UNLIKELY (msg == RUN_RESTART))
{
/* restart */
g_message (_("Restarting xfce4-panel..."));
execvp (argv[0], argv);
}
return EXIT_SUCCESS;
return G_UNLIKELY (msg == RUN_FAILURE) ? EXIT_FAILURE : EXIT_SUCCESS;
}

280
panel/panel-app.c

@ -185,6 +185,7 @@ cleanup_panels (void)
g_ptr_array_free (panel_app.monitor_list, TRUE);
}
/* signal handling */
/** copied from glibc manual, does this prevent zombies? */
@ -210,9 +211,9 @@ static void
sighandler (gint sig)
{
/* Don't do any real stuff here.
* Only set a signal state flag. There's a timeout in the main loop
* that tests the flag.
* This will prevent problems with gtk main loop threads and stuff
* Only write the signal to a pipe. The value will be picked up by a
* g_io_channel watch. This will prevent problems with gtk main loop
* threads and stuff.
*/
if (write (signal_pipe[1], &sig, sizeof (int)) != sizeof (int))
{
@ -221,7 +222,7 @@ sighandler (gint sig)
}
static gboolean
check_run_state (void)
evaluate_run_state (void)
{
static gint recursive = 0;
gboolean quit = FALSE;
@ -267,12 +268,16 @@ check_run_state (void)
if (quit)
{
if (panel_app.save_id)
{
g_source_remove (panel_app.save_id);
panel_app.save_id = 0;
panel_app.save_id = 0;
}
close (signal_pipe[0]);
close (signal_pipe[1]);
/* this is necessary, because the function is not only called from the
* timeout, so just returning FALSE is not enough. */
gtk_main_quit ();
return FALSE;
}
@ -282,37 +287,19 @@ check_run_state (void)
}
static gboolean
set_run_state (GIOChannel *source,
GIOCondition cond,
gpointer data)
signal_pipe_io (GIOChannel *source,
GIOCondition cond,
gpointer data)
{
GError *error = NULL;
GIOStatus status;
gsize bytes_read;
/*
* There is no g_io_channel_read or g_io_channel_read_int, so we read
* char's and use a union to recover the unix signal number.
*/
union
{
gchar chars[sizeof (gint)];
gint signal;
} buf;
gint signal;
gsize bytes_read;
while ((status = g_io_channel_read_chars (source, buf.chars, sizeof (int),
&bytes_read, &error)
) == G_IO_STATUS_NORMAL)
if (G_IO_ERROR_NONE == g_io_channel_read (source, (gchar *)&signal,
sizeof (signal),
&bytes_read)
&& sizeof(signal) == bytes_read)
{
if (bytes_read != sizeof (int))
{
g_printerr ("lost data in signal pipe: expected %d, receieved %d",
sizeof (int), bytes_read);
/* always at least quit if we received data */
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOCONFIRM;
continue;
}
switch (buf.signal)
switch (signal)
{
case SIGUSR1:
DBG ("USR1 signal caught");
@ -336,19 +323,77 @@ set_run_state (GIOChannel *source,
}
}
if (error != NULL)
return evaluate_run_state ();
}
static gboolean
init_signal_pipe ( void )
{
GIOChannel *g_signal_in;
glong fd_flags;
/* create pipe and set writing end in non-blocking mode */
if (pipe (signal_pipe))
{
return FALSE;
}
fd_flags = fcntl (signal_pipe[1], F_GETFL);
if (fd_flags == -1)
{
g_printerr ("reading signal pipe failed: %s\n", error->message);
g_error_free (error);
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOCONFIRM;
return FALSE;
}
if (status != G_IO_STATUS_AGAIN)
if (fcntl (signal_pipe[1], F_SETFL, fd_flags | O_NONBLOCK) == -1)
{
g_printerr ("signal pipe has been closed\n");
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOCONFIRM;
close (signal_pipe[0]);
close (signal_pipe[1]);
return FALSE;
}
return check_run_state ();
/* convert the reading end of the pipe into a GIOChannel */
g_signal_in = g_io_channel_unix_new (signal_pipe[0]);
g_io_channel_set_encoding (g_signal_in, NULL, NULL);
g_io_channel_set_close_on_unref (g_signal_in, FALSE);
/* register the reading end with the event loop */
g_io_add_watch (g_signal_in, G_IO_IN | G_IO_PRI, signal_pipe_io, NULL);
g_io_channel_unref (g_signal_in);
return TRUE;
}
static void
init_signal_handlers ( void )
{
#ifdef HAVE_SIGACTION
struct sigaction act;
act.sa_handler = sighandler;
sigemptyset (&act.sa_mask);
# ifdef SA_RESTART
act.sa_flags = SA_RESTART;
# else
act.sa_flags = 0;
# endif
sigaction (SIGHUP, &act, NULL);
sigaction (SIGUSR1, &act, NULL);
sigaction (SIGUSR2, &act, NULL);
sigaction (SIGINT, &act, NULL);
sigaction (SIGABRT, &act, NULL);
sigaction (SIGTERM, &act, NULL);
act.sa_handler = sigchld_handler;
sigaction (SIGCHLD, &act, NULL);
#else
signal (SIGHUP, sighandler);
signal (SIGUSR1, sighandler);
signal (SIGUSR2, sighandler);
signal (SIGINT, sighandler);
signal (SIGABRT, sighandler);
signal (SIGTERM, sighandler);
signal (SIGCHLD, sigchld_handler);
#endif
}
/* session */
@ -539,8 +584,8 @@ unregister_dialog (GtkWidget *dialog)
* Initialize application. Creates ipc window if no other instance is
* running or sets the ipc window from the running instance.
*
* Returns: 0 on success, 1 when an xfce4-panel instance already exists,
* and -1 on failure.
* Returns: INIT_SUCCESS (0) on success, INIT_RUNNING (1) when an xfce4-panel
* instance already exists, and INIT_FAILURE (2) on failure.
**/
int
panel_app_init (void)
@ -550,7 +595,7 @@ panel_app_init (void)
XClientMessageEvent xev;
if (panel_app.initialized)
return 0;
return INIT_SUCCESS;
panel_app.initialized = TRUE;
@ -559,7 +604,7 @@ panel_app_init (void)
panel_app.ipc_window = XGetSelectionOwner (GDK_DISPLAY (), selection_atom);
if (panel_app.ipc_window)
return 1;
return INIT_RUNNING;
invisible = gtk_invisible_new ();
gtk_widget_realize (invisible);
@ -577,7 +622,7 @@ panel_app_init (void)
{
g_critical ("Could not set ownership of selection \"%s\"",
SELECTION_NAME);
return -1;
return INIT_FAILURE;
}
manager_atom = XInternAtom (GDK_DISPLAY (), "MANAGER", False);
@ -598,7 +643,7 @@ panel_app_init (void)
/* listen for client messages */
panel_app_listen (invisible);
return 0;
return INIT_SUCCESS;
}
/* fix position after showing panel for the first time */
@ -612,14 +657,14 @@ expose_timeout (GtkWidget *panel)
static void
panel_app_init_panel (GtkWidget *panel)
{
TIMER_ELAPSED("start panel_app_init_panel: %p", panel);
MARK("start panel_app_init_panel: %p", panel);
panel_init_position (PANEL (panel));
panel_init_signals (PANEL (panel));
TIMER_ELAPSED(" + start show panel");
MARK(" + start show panel");
gtk_widget_show (panel);
TIMER_ELAPSED(" + end show panel");
MARK(" + end show panel");
g_idle_add ((GSourceFunc)expose_timeout, panel);
TIMER_ELAPSED("end panel_app_init_panel");
MARK("end panel_app_init_panel");
}
/**
@ -628,106 +673,50 @@ panel_app_init_panel (GtkWidget *panel)
* Run the panel application. Reads the configuration file(s) and sets up the
* panels, before turning over control to the main event loop.
*
* Returns: 1 to restart and 0 to quit.
* Returns: RUN_FAILURE (2) if something goes wrong, RUN_RESTART (1) to restart
* and RUN_SUCCESS (0) to quit.
**/
gint
panel_app_run (gchar *client_id)
{
#ifdef HAVE_SIGACTION
struct sigaction act;
#endif
GIOChannel *g_signal_in;
GError *error = NULL;
glong fd_flags;
gchar **restart_command;
/* create pipe and set writing end in non-blocking mode */
if (pipe (signal_pipe))
/* initialize signal handling */
if (!init_signal_pipe ())
{
perror ("pipe");
return -1;
g_critical ("Unable to create signal-watch pipe: %s.",
strerror(errno));
return RUN_FAILURE;
}
fd_flags = fcntl (signal_pipe[1], F_GETFL);
if (fd_flags == -1)
{
perror ("read descriptor flags");
return -1;
}
if (fcntl (signal_pipe[1], F_SETFL, fd_flags | O_NONBLOCK) == -1)
{
perror ("write descriptor flags");
return -1;
}
/* convert the reading end of the pipe into a GIOChannel */
g_signal_in = g_io_channel_unix_new (signal_pipe[0]);
g_io_channel_set_encoding (g_signal_in, NULL, &error);
if (error != NULL)
{ /* handle potential errors */
g_printerr ("g_io_channel_set_encoding failed %s\n",
error->message);
g_error_free (error);
return -1;
}
/* put the reading end also into non-blocking mode */
g_io_channel_set_flags (g_signal_in,
g_io_channel_get_flags (g_signal_in) |
G_IO_FLAG_NONBLOCK, &error);
if (error != NULL)
{
g_printerr ("g_io_set_flags failed %s\n", error->message);
g_error_free (error);
return -1;
}
/* register the reading end with the event loop */
g_io_add_watch (g_signal_in, G_IO_IN | G_IO_PRI, set_run_state, NULL);
/* register signals */
#ifdef HAVE_SIGACTION
act.sa_handler = sighandler;
sigemptyset (&act.sa_mask);
#ifdef SA_RESTART
act.sa_flags = SA_RESTART;
#else
act.sa_flags = 0;
#endif
sigaction (SIGHUP, &act, NULL);
sigaction (SIGUSR1, &act, NULL);
sigaction (SIGUSR2, &act, NULL);
sigaction (SIGINT, &act, NULL);
sigaction (SIGABRT, &act, NULL);
sigaction (SIGTERM, &act, NULL);
act.sa_handler = sigchld_handler;
sigaction (SIGCHLD, &act, NULL);
#else
signal (SIGHUP, sighandler);
signal (SIGUSR1, sighandler);
signal (SIGUSR2, sighandler);
signal (SIGINT, sighandler);
signal (SIGABRT, sighandler);
signal (SIGTERM, sighandler);
signal (SIGCHLD, sigchld_handler);
#endif
init_signal_handlers ();
/* environment */
xfce_setenv ("DISPLAY", gdk_display_get_name (gdk_display_get_default ()), TRUE);
xfce_setenv ("DISPLAY",
gdk_display_get_name (gdk_display_get_default ()),
TRUE);
/* session management */
restart_command = g_new (gchar *, 2);
restart_command = g_new (gchar *, 2);
restart_command[0] = "xfce4-panel";
restart_command[1] = "-r";
restart_command[2] = NULL;
panel_app.session_client = client_session_new_full (NULL, SESSION_RESTART_IF_RUNNING,
40, client_id, PACKAGE_NAME, NULL,
restart_command, restart_command,
NULL, NULL, NULL);
panel_app.session_client =
client_session_new_full (NULL,
SESSION_RESTART_IF_RUNNING,
40,
client_id,
PACKAGE_NAME,
NULL,
restart_command,
restart_command,
NULL,
NULL,
NULL);
panel_app.session_client->save_yourself = session_save_yourself;
panel_app.session_client->die = session_die;
TIMER_ELAPSED("connect to session manager");
MARK("connect to session manager");
if (!session_init (panel_app.session_client))
{
g_free (panel_app.session_client);
@ -735,24 +724,25 @@ panel_app_run (gchar *client_id)
}
/* screen layout and geometry */
TIMER_ELAPSED("start monitor list creation");
MARK("start monitor list creation");
create_monitor_list ();
/* configuration */
TIMER_ELAPSED("start init item manager");
MARK("start init item manager");
xfce_panel_item_manager_init ();
TIMER_ELAPSED("start panel creation");
MARK("start panel creation");
panel_app.panel_list = panel_config_create_panels ();
TIMER_ELAPSED("end panel creation");
MARK("end panel creation");
g_ptr_array_foreach (panel_app.panel_list, (GFunc)panel_app_init_panel,
NULL);
/* Run Forrest, Run! */
panel_app.runstate = PANEL_RUN_STATE_NORMAL;
TIMER_ELAPSED("start main loop");
MARK("start main loop");
gtk_main ();
MARK("end main loop");
/* cleanup */
g_free (panel_app.session_client);
@ -762,9 +752,9 @@ panel_app_run (gchar *client_id)
xfce_panel_item_manager_cleanup ();
if (panel_app.runstate == PANEL_RUN_STATE_RESTART)
return 1;
return RUN_RESTART;
return 0;
return RUN_SUCCESS;
}
static gboolean
@ -827,28 +817,28 @@ void
panel_app_restart (void)
{
panel_app.runstate = PANEL_RUN_STATE_RESTART;
check_run_state ();
evaluate_run_state ();
}
void
panel_app_quit (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT;
check_run_state ();
evaluate_run_state ();
}
void
panel_app_quit_noconfirm (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOCONFIRM;
check_run_state ();
evaluate_run_state ();
}
void
panel_app_quit_nosave (void)
{
panel_app.runstate = PANEL_RUN_STATE_QUIT_NOSAVE;
check_run_state ();
evaluate_run_state ();
}
void

20
panel/panel-app.h

@ -31,17 +31,16 @@ typedef struct _XfceMonitor XfceMonitor;
void xfce_panel_program_log (const char *file, const int line,
const char *format, ...);
#define TIMER_ELAPSED(...) \
#define MARK(...) \
xfce_panel_program_log (__FILE__, __LINE__, __VA_ARGS__)
#else
#define TIMER_ELAPSED(fmt,args...) do {} while(0)
#define MARK(fmt,args...) do {} while(0)
#endif /* TIMER */
struct _XfceMonitor
{
GdkScreen *screen;
@ -53,6 +52,21 @@ struct _XfceMonitor
guint has_neighbor_below : 1;
};
/* return status */
enum {
INIT_SUCCESS,
INIT_RUNNING,
INIT_FAILURE
};
enum {
RUN_SUCCESS,
RUN_RESTART,
RUN_FAILURE,
};
/* run control */
int panel_app_init (void);

14
panel/panel-config.c

@ -316,19 +316,19 @@ start_element_handler (GMarkupParseContext *context,
parser->current_panel = panel_new ();
g_ptr_array_add (parser->panels, parser->current_panel);
init_properties (parser);
TIMER_ELAPSED(" + start config panel");
MARK(" + start config panel");
}
break;
case PANEL:
if (strcmp (element_name, "properties") == 0)
{
TIMER_ELAPSED(" ++ start properties");
MARK(" ++ start properties");
parser->state = PROPERTIES;
}
else if (strcmp (element_name, "items") == 0)
{
TIMER_ELAPSED(" ++ start items");
MARK(" ++ start items");
parser->state = ITEMS;
}
break;
@ -380,7 +380,7 @@ start_element_handler (GMarkupParseContext *context,
{
DBG ("Add item: name=\"%s\", id=\"%s\"", name, value);
TIMER_ELAPSED(" +++ add item: %s", name);
MARK(" +++ add item: %s", name);
panel_add_item_with_id (parser->current_panel,
name, value);
}
@ -421,7 +421,7 @@ end_element_handler (GMarkupParseContext *context,
{
parser->state = PANELS;
parser->current_panel = NULL;
TIMER_ELAPSED(" + end config panel");
MARK(" + end config panel");
}
break;
@ -454,7 +454,7 @@ end_element_handler (GMarkupParseContext *context,
"activetrans", parser->activetrans,
NULL);
}
TIMER_ELAPSED(" ++ end properties");
MARK(" ++ end properties");
}
break;
@ -462,7 +462,7 @@ end_element_handler (GMarkupParseContext *context,
if (strcmp ("items", element_name) == 0)
{
parser->state = PANEL;
TIMER_ELAPSED(" ++ end items");
MARK(" ++ end items");
}
break;

Loading…
Cancel
Save