| @@ -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 | |||
| @@ -467,6 +467,7 @@ body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-b | |||
| <ul class="sectlevel4"> | |||
| <li><a href="#_subdirectories_hierarchical_structure">1.2.3.1. Subdirectories / Hierarchical Structure</a></li> | |||
| <li><a href="#_lockfiles">1.2.3.2. Lockfiles</a></li> | |||
| <li><a href="#_daemon_discovery">1.2.3.3. Daemon Discovery</a></li> | |||
| </ul> | |||
| </li> | |||
| </ul> | |||
| @@ -796,6 +797,19 @@ osc.udp://myuser.localdomain:11287/ | |||
| </div> | |||
| </div> | |||
| </div> | |||
| <div class="sect4"> | |||
| <h5 id="_daemon_discovery">1.2.3.3. Daemon Discovery</h5> | |||
| <div class="paragraph"> | |||
| <p>Each running <code>nsmd</code>, per user, creates a state file under <code>$XDG_RUNTIME_DIR/nsm/d/</code> (usually | |||
| <code>/run/user/XXXX/nsm/d/</code>) 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.</p> | |||
| </div> | |||
| <div class="paragraph"> | |||
| <p>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.</p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -1871,7 +1885,7 @@ behaviour more strictly as well, removing false session entries in 3rd party cli | |||
| <li> | |||
| <p>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.</p> | |||
| "background information" in the chapters for lock files and daemon disovery.</p> | |||
| </li> | |||
| </ul> | |||
| </div> | |||
| @@ -1882,7 +1896,7 @@ if of no consequence to clients but required documentation nevertheless, which w | |||
| <div id="footer"> | |||
| <div id="footer-text"> | |||
| Version API 1.1.2<br> | |||
| Last updated 2022-03-05 12:34:04 +0100 | |||
| Last updated 2022-03-15 18:44:44 +0100 | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -557,7 +557,7 @@ Documentation and tutorials for software-developers will be added at a later dat | |||
| <div id="footer"> | |||
| <div id="footer-text"> | |||
| Version 1.6.0<br> | |||
| Last updated 2022-03-05 12:34:04 +0100 | |||
| Last updated 2022-03-15 18:44:44 +0100 | |||
| </div> | |||
| </div> | |||
| </body> | |||
| @@ -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. | |||
| @@ -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; | |||
| } | |||