@@ -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; | |||
} |