@@ -703,6 +703,9 @@ database files and log files; by default, it is the
.I var/pseudo
directory under
.BR PSEUDO_PREFIX .
+It must be writable; if it is not,
+.I pseudo
+fails at startup rather than trying to start the server.
.TP 8
.B PSEUDO_NOSYMLINKEXP
By default, when chrooted,
@@ -608,6 +608,16 @@ pseudo_init_client(void) {
strerror(errno));
exit(1);
}
+ /* the server can't run without creating its lock,
+ * socket, pid and database files here, so fail now
+ * instead of repeatedly trying to start it
+ */
+ if (faccessat(pseudo_localstate_dir_fd, ".", W_OK | X_OK, 0) == -1) {
+ pseudo_error("Local state path '%s' is not writable: %s\n",
+ pseudo_path,
+ strerror(errno));
+ exit(1);
+ }
}
free(pseudo_path);
@@ -1028,6 +1038,22 @@ client_spawn_server(void) {
} else {
pseudo_evlog(PDBGF_CLIENT, "server startup apparently unsuccessful. setting server pid to -1.\n");
server_pid = -1;
+ /* Retrying can't fix these, so stop instead of
+ * respawning the server PSEUDO_RETRIES times.
+ */
+ if (WIFEXITED(status)) {
+ switch (WEXITSTATUS(status)) {
+ case PSEUDO_EXIT_LOCK_PATH:
+ case PSEUDO_EXIT_PSEUDO_LOADED:
+ case PSEUDO_EXIT_PSEUDO_PREFIX:
+ case PSEUDO_EXIT_PSEUDO_INVOCATION:
+ pseudo_critical("server failed to start: %s\n",
+ pseudo_exit_status_name(WEXITSTATUS(status)));
+ break;
+ default:
+ break;
+ }
+ }
return 1;
}
} else {
@@ -266,6 +266,11 @@ pseudo_server_start(int daemonize) {
exit(PSEUDO_EXIT_LOCK_PATH);
}
mkdir_p(lockpath);
+ if (access(lockpath, W_OK | X_OK) == -1) {
+ pseudo_error("Local state directory '%s' is not writable, unable to create lockfile: %s\n",
+ lockpath, strerror(errno));
+ exit(PSEUDO_EXIT_LOCK_FAILED);
+ }
lockname = pseudo_localstatedir_path(PSEUDO_LOCKFILE);
if (!lockname) {
pseudo_error("Couldn't allocate a file path.\n");
A read-only PSEUDO_LOCALSTATEDIR was only opened for reading, so clients kept spawning a server that couldn't create its lock file, up to PSEUDO_RETRIES times with an error each time, before aborting. Check the directory is writable when the client starts, and fail as for a missing directory. The server makes the same check before creating its lock file. The client also aborts at once if the server exits with a status retrying can't fix; lock_failed is still retried, as running out of file descriptors can cause it. Tested with a chmod 555 directory, a read-only bind mount, and by starting the server directly. [YOCTO #15497] Reported-by: milahu <milahu@gmail.com> AI-Generated: Uses GitHub Copilot Signed-off-by: Mark Hatle <mark.hatle@amd.com> --- pseudo.1 | 3 +++ pseudo_client.c | 26 ++++++++++++++++++++++++++ pseudo_server.c | 5 +++++ 3 files changed, 34 insertions(+)