diff --git a/CHANGELOG b/CHANGELOG index c3bbf29..0efa29f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -12,6 +12,7 @@ nsmd now follows the XDG Base Directory Specifications: Lockfiles fixed (see issue #gh-31) Lockfiles are now in $XDG_RUNTIME_DIR/nsm/ Lockfiles now each contain the session path, the osc NSM_URL and the nsmd PID + One daemon file for each currently running nsmd is created in $XDG_RUNTIME_DIR/nsm/d/ containing the osc url. This enables discovery of running daemons. New section in the API documentation for the above. Fixes and guards against trying to load non-existing sessions and creating new sessions under existing names diff --git a/docs/api/index.html b/docs/api/index.html index 9aa861e..a678630 100644 --- a/docs/api/index.html +++ b/docs/api/index.html @@ -467,6 +467,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b @@ -796,6 +797,19 @@ osc.udp://myuser.localdomain:11287/ +
+
1.2.3.3. Daemon Discovery
+
+

Each running nsmd, per user, creates a state file under $XDG_RUNTIME_DIR/nsm/d/ (usually +/run/user/XXXX/nsm/d/) that can be used to look up running daemons, even if no session is loaded. +The files contains the daemons osc.udp URL that is compatible with the --nsm-url parameter of the GUI.

+
+
+

This enables you to e.g. start nsmd at boot with a random free port. Server-control programs such +as GUIs can then use this to look for running servers without requiring the user to look up and +input an osc URL manually as command line parameter.

+
+
@@ -1871,7 +1885,7 @@ behaviour more strictly as well, removing false session entries in 3rd party cli
  • nsmd now follows the XDG Base Directory Specifications for it’s session root and lock files. This if of no consequence to clients but required documentation nevertheless, which was described as -"background information" in the new section.

    +"background information" in the chapters for lock files and daemon disovery.

  • @@ -1882,7 +1896,7 @@ if of no consequence to clients but required documentation nevertheless, which w diff --git a/docs/index.html b/docs/index.html index 97cf4a0..84500fd 100644 --- a/docs/index.html +++ b/docs/index.html @@ -557,7 +557,7 @@ Documentation and tutorials for software-developers will be added at a later dat diff --git a/docs/src/api/index.adoc b/docs/src/api/index.adoc index bd394ba..abec626 100644 --- a/docs/src/api/index.adoc +++ b/docs/src/api/index.adoc @@ -230,6 +230,18 @@ osc.udp://myuser.localdomain:11287/ 3022 ``` +===== Daemon Discovery + +Each running `nsmd`, per user, creates a state file under `$XDG_RUNTIME_DIR/nsm/d/` (usually +`/run/user/XXXX/nsm/d/`) that can be used to look up running daemons, even if no session is loaded. +The files contains the daemons osc.udp URL that is compatible with the --nsm-url parameter of the GUI. + + +This enables you to e.g. start nsmd at boot with a random free port. Server-control programs such +as GUIs can then use this to look for running servers without requiring the user to look up and +input an osc URL manually as command line parameter. + + == NSM OSC Protocol All message parameters are REQUIRED. All messages MUST be sent from the same socket as the `announce` @@ -908,4 +920,4 @@ behaviour more strictly as well, removing false session entries in 3rd party cli * nsmd now follows the XDG Base Directory Specifications for it's session root and lock files. This if of no consequence to clients but required documentation nevertheless, which was described as -"background information" in the new section. +"background information" in the chapters for lock files and daemon disovery. diff --git a/src/nsmd.cpp b/src/nsmd.cpp index d73f0b5..552397f 100644 --- a/src/nsmd.cpp +++ b/src/nsmd.cpp @@ -64,6 +64,7 @@ static int signal_fd; static char *session_root; static char *lockfile_directory; +static char *daemon_file; #define NSM_API_VERSION_MAJOR 1 #define NSM_API_VERSION_MINOR 1 @@ -2584,6 +2585,10 @@ handle_signal_clean_exit ( int signal ) close_session(); free( session_root ); free( lockfile_directory ); + unlink( daemon_file ); + MESSAGE( "Deleted daemon file %s", daemon_file ); + free( daemon_file ); + exit(0); } @@ -2717,9 +2722,24 @@ int main(int argc, char *argv[]) } } MESSAGE( "Using %s for lock-files.", lockfile_directory ); - } - + //Now create another subdir for daemons .../nsm/d/ where each daemon has a port number file + char * daemon_directory; + asprintf( &daemon_directory, "%s/d", lockfile_directory); + struct stat st_daemonfile_dir_mkdir; + if ( stat( daemon_directory, &st_daemonfile_dir_mkdir ) ) + { + if ( mkdir( daemon_directory, 0771 ) ) + { + FATAL( "Failed to create daemon file directory %s with error: %s", daemon_directory, strerror( errno ) ); + } + } + //daemon_file is a global var + asprintf( &daemon_file, "%s/%d", daemon_directory, getpid()); + free ( daemon_directory ); + MESSAGE( "Using %s as daemon file.", daemon_file ); + //The actual daemon file will be written below after announcing the session url. + } if ( !session_root ) { /* The user gave no specific session directory. We use the default. @@ -2736,6 +2756,7 @@ int main(int argc, char *argv[]) */ struct stat st_session_root; + //TODO: Valgrind shows a memory leak for the next line. Why? asprintf( &session_root, "%s/%s", getenv( "HOME" ), "NSM Sessions" ); if ( stat( session_root, &st_session_root ) == 0 && S_ISDIR(st_session_root.st_mode)) { WARNING ( "An old session directory was detected in %s. You can continue to use it but it is recommended to move your sessions to $XDG_DATA_HOME/nsm-sessions/. If you don't know where that is simply rename your current session-directory and start nsmd, which will tell you the new directory.", session_root); @@ -2775,7 +2796,20 @@ int main(int argc, char *argv[]) FATAL( "Failed to create OSC server." ); } - printf( "NSM_URL=%s\n", osc_server->url() ); + char * url = osc_server->url(); + + printf( "NSM_URL=%s\n", url ); + + //Write the URL into the daemon_file that is named after our PID + FILE *fpdaemon = fopen( daemon_file, "w" ); + if ( !fpdaemon ) { + FATAL( "Failed to write daemon file to %s with error: %s", daemon_file, strerror( errno ) ); + } + fprintf( fpdaemon, "%s\n", url ); + MESSAGE( "Created daemon file %s", daemon_file ); + fclose( fpdaemon ); + + free( url ); if ( gui_url ) { @@ -2847,24 +2881,20 @@ int main(int argc, char *argv[]) } /* listen for sigchld signals and process OSC messages forever */ - int start_pid = getppid(); //get parent pid + int start_ppid = getppid(); //get parent pid for ( ;; ) { wait( 1000 ); //1000 ms //This still has some corner cases, like a race condition on startup that never gets the real PID, but //we cover the majority of cases at least: - if ( start_pid != getppid() ) { - WARNING ( "Our parent PID changed from %d to %d, which indicates a possible GUI crash. The user has no control over the session anymore. Trying to shut down cleanly.", start_pid, getppid()); + if ( start_ppid != getppid() ) { + WARNING ( "Our parent PID changed from %d to %d, which indicates a possible GUI crash. The user has no control over the session anymore. Trying to shut down cleanly.", start_ppid, getppid()); handle_signal_clean_exit ( 0 ); } } //Code after here will not be executed if nsmd is stopped with any abort-signal like SIGINT. //Without a signal handler clients will remain active ("zombies") without nsmd as parent. - //MESSAGE ( "End of Program"); - - //free(session_root);// This was not executed if nsmd received a stop signal. It is now handled by handle_signal_clean_exit() - //osc_server->run(); - + //Therefore exit is handled by handle_signal_clean_exit() return 0; }