[pkg-fso-commits] [SCM] Automatic Display Manager branch, bug540201, updated. debian/0.6-1-47-gdf7e033
Enrico Zini
enrico at enricozini.org
Wed Jul 6 15:20:43 UTC 2011
The following commit has been merged in the bug540201 branch:
commit bac4dd3abe9be22596aac6b22c0701b341c8d380
Author: Enrico Zini <enrico at enricozini.org>
Date: Wed Jul 6 17:20:35 2011 +0200
Cleaned up wait/restart loop
diff --git a/dm.c b/dm.c
index f23ed6c..57639ce 100644
--- a/dm.c
+++ b/dm.c
@@ -28,6 +28,7 @@
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
+#include <unistd.h>
void nodm_display_manager_init(struct nodm_display_manager* dm)
@@ -35,12 +36,15 @@ void nodm_display_manager_init(struct nodm_display_manager* dm)
nodm_xserver_init(&dm->srv);
nodm_xsession_init(&dm->session);
nodm_vt_init(&dm->vt);
+ dm->conf_minimum_session_time = atoi(getenv_with_default("NODM_MIN_SESSION_TIME", "60"));
dm->_srv_split_args = NULL;
dm->_srv_split_argv = NULL;
}
void nodm_display_manager_cleanup(struct nodm_display_manager* dm)
{
+ nodm_vt_stop(&dm->vt);
+
// Deallocate parsed arguments, if used
if (dm->_srv_split_args)
{
@@ -73,7 +77,17 @@ int nodm_display_manager_start(struct nodm_display_manager* dm)
*s = NULL;
}
- res = nodm_xserver_start(&dm->srv);
+ dm->last_session_start = time(NULL);
+
+ res = nodm_display_manager_restart(dm);
+ if (res != E_SUCCESS) return res;
+
+ return E_SUCCESS;
+}
+
+int nodm_display_manager_restart(struct nodm_display_manager* dm)
+{
+ int res = nodm_xserver_start(&dm->srv);
if (res != E_SUCCESS) return res;
res = nodm_xsession_start(&dm->session, &dm->srv);
@@ -90,8 +104,6 @@ int nodm_display_manager_stop(struct nodm_display_manager* dm)
res = nodm_xserver_stop(&dm->srv);
if (res != E_SUCCESS) return res;
- nodm_vt_stop(&dm->vt);
-
return E_SUCCESS;
}
@@ -214,3 +226,50 @@ void nodm_display_manager_dump_status(struct nodm_display_manager* dm)
nodm_xserver_dump_status(&dm->srv);
nodm_xsession_dump_status(&dm->session);
}
+
+int nodm_display_manager_wait_restart_loop(struct nodm_display_manager* dm)
+{
+ static int retry_times[] = { 0, 0, 30, 30, 60, 60, -1 };
+ int restart_count = 0;
+ int res;
+
+ while (1)
+ {
+ int sstatus;
+ res = nodm_display_manager_wait(dm, &sstatus);
+ time_t end = time(NULL);
+ nodm_display_manager_stop(dm);
+
+ switch (res)
+ {
+ case E_X_SERVER_DIED:
+ break;
+ case E_SESSION_DIED:
+ log_info("X session quit with status %d", sstatus);
+ break;
+ default:
+ return res;
+ }
+
+ /* Check if the session was too short */
+ if (end - dm->last_session_start < dm->conf_minimum_session_time)
+ {
+ if (retry_times[restart_count+1] != -1)
+ ++restart_count;
+ }
+ else
+ restart_count = 0;
+
+ /* Sleep a bit if the session was too short */
+ if (retry_times[restart_count] > 0)
+ {
+ log_warn("session lasted less than %d seconds: sleeping %d seconds before restarting it",
+ dm->conf_minimum_session_time, retry_times[restart_count]);
+ sleep(retry_times[restart_count]);
+ }
+
+ log_info("restarting session");
+ res = nodm_display_manager_restart(dm);
+ if (res != E_SUCCESS) return res;
+ }
+}
diff --git a/dm.h b/dm.h
index e10d504..051965e 100644
--- a/dm.h
+++ b/dm.h
@@ -24,6 +24,7 @@
#include "xserver.h"
#include "xsession.h"
#include "vt.h"
+#include <time.h>
struct nodm_display_manager
{
@@ -36,6 +37,15 @@ struct nodm_display_manager
/// VT allocation
struct nodm_vt vt;
+ /**
+ * The minimum time (in seconds) that a session should last to be
+ * considered successful
+ */
+ int conf_minimum_session_time;
+
+ /// Time the last session started
+ time_t last_session_start;
+
/// Storage for split server arguments used by nodm_x_cmdline_split
char** _srv_split_argv;
void* _srv_split_args;
@@ -53,15 +63,26 @@ void nodm_display_manager_cleanup(struct nodm_display_manager* dm);
/// Start X and the X session
int nodm_display_manager_start(struct nodm_display_manager* dm);
+/// Restart X and the X session after they died
+int nodm_display_manager_restart(struct nodm_display_manager* dm);
+
/// Wait for X or the X session to end
int nodm_display_manager_wait(struct nodm_display_manager* dm, int* session_status);
-// TODO: int nodm_display_manager_restart(struct nodm_display_manager* dm);
-
/// Stop X and the X session
int nodm_display_manager_stop(struct nodm_display_manager* dm);
/**
+ * nodm wait/restart loop.
+ *
+ * Wait for the X server or session to terminate and restart them.
+ *
+ * If the session was very short-lived, it wants for an incremental amount of
+ * time before restarting it.
+ */
+int nodm_display_manager_wait_restart_loop(struct nodm_display_manager* dm);
+
+/**
* Split xcmdline using wordexp shell-like expansion and set dm->srv.argv.
*
* If the first token starts with '/' or '.', it is used as the X server, else
diff --git a/nodm.c b/nodm.c
index 9b95a3e..8f4a930 100644
--- a/nodm.c
+++ b/nodm.c
@@ -40,96 +40,7 @@
#include <time.h>
#include <unistd.h>
-
-#define _(...) (__VA_ARGS__)
-
-/* Program name used in error messages */
-static const char *Prog;
-
-/*
- * Run the X session
- *
- * @param xsession
- * The path to the X session
- * @param xoptions
- * X options (can be NULL if no options are to be passed)
- * @param mst
- * The minimum time (in seconds) that a session should last to be considered
- * successful
- */
-void run_and_restart(const char* xsession, const char* xoptions, int mst)
-{
- static int retry_times[] = { 0, 0, 30, 30, 60, 60, -1 };
- int restart_count = 0;
- /*
- char command[BUFSIZ];
- const char* args[4];
-
- if (xoptions != NULL)
- snprintf(command, BUFSIZ, "exec %s %s -- %s", xinit, xsession, xoptions);
- else
- snprintf(command, BUFSIZ, "exec %s %s", xinit, xsession);
- command[BUFSIZ-1] = 0;
-
- args[0] = "/bin/sh";
- args[1] = "-c";
- args[2] = command;
- args[3] = 0;
- */
-
- while (1)
- {
- struct nodm_display_manager dm;
- nodm_display_manager_init(&dm);
-
- int status = nodm_display_manager_parse_xcmdline(&dm, xoptions);
- if (status != E_SUCCESS)
- exit(status);
-
- /* Run the X server */
- time_t begin = time(NULL);
- time_t end;
- // TODO status = nodm_x_with_session(&s);
- log_info("X session exited with status %d", status);
- end = time(NULL);
- nodm_display_manager_cleanup(&dm);
-
- /* Check if the session was too short */
- if (end - begin < mst)
- {
- log_warn("session was shorter than %d seconds: possible problems", mst);
- if (retry_times[restart_count+1] != -1)
- ++restart_count;
- }
- else
- restart_count = 0;
-
- /* Sleep a bit if the session was too short */
- sleep(retry_times[restart_count]);
- log_info("restarting session");
- }
-}
-
-/*
- * Copy from the environment the value of $name into dest.
- *
- * If $name is not in the environment, use def.
- *
- * @param destination buffer, should be at least BUFSIZ long
- * @param name name of the environment variable to look up
- * @param def default value to use if $name is not found
- */
-static void string_from_env(char* dest, const char* name, const char* def)
-{
- char* cp = getenv(name);
- if (cp != NULL)
- strncpy(dest, cp, BUFSIZ-1);
- else
- strncpy(dest, def, BUFSIZ-1);
- dest[BUFSIZ-1] = 0;
-}
-
-static void monitor_cmdline_help(int argc, char** argv, FILE* out)
+static void do_help(int argc, char** argv, FILE* out)
{
fprintf(out, "Usage: %s [options]\n\n", argv[0]);
fprintf(out, "Options:\n");
@@ -139,73 +50,6 @@ static void monitor_cmdline_help(int argc, char** argv, FILE* out)
fprintf(out, " (use for testing)\n");
}
-/*
- * Start the monitor, that will continue to rerun xinit with appropriate delays
- */
-static int nodm_monitor(int argc, char **argv)
-{
- static int opt_help = 0;
- static int opt_version = 0;
- static struct option options[] =
- {
- /* These options set a flag. */
- {"help", no_argument, &opt_help, 1},
- {"version", no_argument, &opt_version, 1},
- {"session", required_argument, 0, 's'},
- {0, 0, 0, 0}
- };
- const char* opt_session = NODM_SESSION;
- char xoptions[BUFSIZ];
- char* cp;
- int mst;
-
- /* Parse command line options */
- while (1)
- {
- int option_index = 0;
- int c = getopt_long(argc, argv, "s:", options, &option_index);
- if (c == -1) break;
- switch (c)
- {
- case 0: break;
- case 's': opt_session = optarg; break;
- default:
- fprintf(stderr, "Invalid command line option\n");
- monitor_cmdline_help(argc, argv, stderr);
- return 1;
- }
- }
- if (opt_help)
- {
- monitor_cmdline_help(argc, argv, stdout);
- return 0;
- }
- if (opt_version)
- {
- printf("%s version %s\n", NAME, VERSION);
- return 0;
- }
-
- /* We only run if we are root */
- if (getuid() != 0)
- {
- fprintf (stderr, _("%s: can only be run by root\n"), Prog);
- return E_NOPERM;
- }
-
- log_info("starting nodm monitor");
-
- /* Read the configuration from the environment */
- cp = getenv("NODM_MIN_SESSION_TIME");
- mst = cp ? atoi(cp) : 60;
- string_from_env(xoptions, "NODM_X_OPTIONS", "");
-
- setenv("NODM_RUN_SESSION", "1", 1);
- run_and_restart(opt_session, xoptions, mst);
-
- return 0;
-}
-
/*
* nodm - start X with autologin to a given user
@@ -217,28 +61,76 @@ static int nodm_monitor(int argc, char **argv)
*/
int main (int argc, char **argv)
{
- /*
- * Get the program name. The program name is used as a prefix to
- * most error messages.
- */
- Prog = basename(argv[0]);
-
- // TODO: move these after command line parsing, so we can implement
- // --verbose --no-syslog --no-stderr and the like
+ static int opt_help = 0;
+ static int opt_version = 0;
+ static struct option options[] =
+ {
+ /* These options set a flag. */
+ {"help", no_argument, &opt_help, 1},
+ {"version", no_argument, &opt_version, 1},
+ {0, 0, 0, 0}
+ };
+
+ // Parse command line options
+ while (1)
+ {
+ int option_index = 0;
+ int c = getopt_long(argc, argv, ":", options, &option_index);
+ if (c == -1) break;
+ switch (c)
+ {
+ case 0: break;
+ default:
+ fprintf(stderr, "Invalid command line option\n");
+ do_help(argc, argv, stderr);
+ return E_USAGE;
+ }
+ }
+ if (opt_help)
+ {
+ do_help(argc, argv, stdout);
+ return E_SUCCESS;
+ }
+ if (opt_version)
+ {
+ printf("%s version %s\n", NAME, VERSION);
+ return E_SUCCESS;
+ }
+
+ // We only run if we are root
+ if (getuid() != 0)
+ {
+ fprintf(stderr, "%s: can only be run by root\n", basename(argv[0]));
+ return E_NOPERM;
+ }
+
+ // TODO: implement --verbose --no-syslog --no-stderr and the like
struct log_config cfg = {
- .program_name = Prog,
+ .program_name = basename(argv[0]),
.log_to_syslog = true,
- .log_to_stderr = true,
+ .log_to_stderr = false,
.info_to_stderr = false,
+ .verbose = false
};
log_start(&cfg);
- /*
- * Process the command line arguments.
- */
+ log_info("starting nodm");
+
+ // Run the display manager
+ struct nodm_display_manager dm;
+ nodm_display_manager_init(&dm);
+
+ int res = nodm_display_manager_parse_xcmdline(&dm, getenv_with_default("NODM_X_OPTIONS", ""));
+ if (res != E_SUCCESS) goto cleanup;
+
+ res = nodm_display_manager_start(&dm);
+ if (res != E_SUCCESS) goto cleanup;
- int ret = nodm_monitor(argc, argv);
+ res = nodm_display_manager_wait_restart_loop(&dm);
+ if (res != E_SUCCESS) goto cleanup;
+cleanup:
+ nodm_display_manager_cleanup(&dm);
log_end();
- return ret;
+ return res;
}
diff --git a/xsession-child.c b/xsession-child.c
index 18a6e23..a483d36 100644
--- a/xsession-child.c
+++ b/xsession-child.c
@@ -327,7 +327,6 @@ int nodm_xsession_child_common_env(struct nodm_xsession_child* s)
unsetenv("NODM_XSESSION");
unsetenv("NODM_X_OPTIONS");
unsetenv("NODM_MIN_SESSION_TIME");
- unsetenv("NODM_RUN_SESSION");
// Move to home directory
if (chdir(s->pwent.pw_dir) == 0)
--
Automatic Display Manager
More information about the pkg-fso-commits
mailing list