1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 04:10:54 -08:00

Fix server-name' and server-socket-dir' for (Bug#24218)

* lisp/server.el: (server-external-socket-initialised): New
(server-name): Compute server name from `get-external-sockname'.
(server-socket-dir): Compute socket dir from
`get-external-sockname'.
(server-start): Don't check for existing server when an
uninitialised external socket has been passed to Emacs.
* src/emacs.c: (main): Obtain socket name via getsockname and pass
to `init_process_emacs'.
* src/lisp.h: (init_process_emacs): Add second parameter.
* src/process.c: (external_sock_name): New.
(get-external-sockname): New.
(init_process_emacs): Set `external_sock_name' to `sockname'
parameter.
This commit is contained in:
Matthew Leach 2018-02-12 12:52:43 -08:00 committed by Paul Eggert
parent b3f45140ec
commit e1ca0ea872
4 changed files with 68 additions and 25 deletions

View file

@ -251,8 +251,16 @@ This means that the server should not kill the buffer when you say you
are done with it in the server.")
(make-variable-buffer-local 'server-existing-buffer)
;;;###autoload
(defcustom server-name "server"
(defvar server-external-socket-initialised nil
"When an external socket is passed into Emacs, we need to call
`server-start' in order to initialise the connection. This flag
prevents multiple initialisations when an external socket has
been consumed.")
(defcustom server-name
(if (get-external-sockname)
(file-name-nondirectory (get-external-sockname))
"server")
"The name of the Emacs server, if this Emacs process creates one.
The command `server-start' makes use of this. It should not be
changed while a server is running."
@ -263,8 +271,10 @@ changed while a server is running."
;; We do not use `temporary-file-directory' here, because emacsclient
;; does not read the init file.
(defvar server-socket-dir
(and (featurep 'make-network-process '(:family local))
(format "%s/emacs%d" (or (getenv "TMPDIR") "/tmp") (user-uid)))
(if (get-external-sockname)
(file-name-directory (get-external-sockname))
(and (featurep 'make-network-process '(:family local))
(format "%s/emacs%d" (or (getenv "TMPDIR") "/tmp") (user-uid))))
"The directory in which to place the server socket.
If local sockets are not supported, this is nil.")
@ -618,23 +628,29 @@ To force-start a server, do \\[server-force-delete] and then
(when server-process
;; kill it dead!
(ignore-errors (delete-process server-process)))
;; Delete the socket files made by previous server invocations.
(if (not (eq t (server-running-p server-name)))
;; Remove any leftover socket or authentication file
(ignore-errors
(let (delete-by-moving-to-trash)
(delete-file server-file)))
(setq server-mode nil) ;; already set by the minor mode code
(display-warning
'server
(concat "Unable to start the Emacs server.\n"
(format "There is an existing Emacs server, named %S.\n"
server-name)
(substitute-command-keys
"To start the server in this Emacs process, stop the existing
;; Check to see if an uninitialised external socket has been
;; passed in, if that is the case, skip checking
;; `server-running-p' as this will return the wrong result.
(if (and (get-external-sockname)
(not server-external-socket-initialised))
(setq server-external-socket-initialised t)
;; Delete the socket files made by previous server invocations.
(if (not (eq t (server-running-p server-name)))
;; Remove any leftover socket or authentication file
(ignore-errors
(let (delete-by-moving-to-trash)
(delete-file server-file)))
(setq server-mode nil) ;; already set by the minor mode code
(display-warning
'server
(concat "Unable to start the Emacs server.\n"
(format "There is an existing Emacs server, named %S.\n"
server-name)
(substitute-command-keys
"To start the server in this Emacs process, stop the existing
server or call `\\[server-force-delete]' to forcibly disconnect it."))
:warning)
(setq leave-dead t))
:warning)
(setq leave-dead t)))
;; If this Emacs already had a server, clear out associated status.
(while server-clients
(server-delete-client (car server-clients)))

View file

@ -60,6 +60,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef HAVE_LIBSYSTEMD
# include <systemd/sd-daemon.h>
# include <sys/socket.h>
# include <sys/un.h>
#endif
#ifdef HAVE_WINDOW_SYSTEM
@ -1002,6 +1003,7 @@ main (int argc, char **argv)
int sockfd = -1;
char *sockname = NULL;
if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, &skip_args)
|| argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, &skip_args))
@ -1061,8 +1063,16 @@ main (int argc, char **argv)
"Try 'Accept=false' in the Emacs socket unit file.\n"));
else if (systemd_socket == 1
&& (0 < sd_is_socket (SD_LISTEN_FDS_START,
AF_UNSPEC, SOCK_STREAM, 1)))
sockfd = SD_LISTEN_FDS_START;
AF_UNIX, SOCK_STREAM, 1)))
{
struct sockaddr_un sockaddr;
socklen_t sockaddr_sz = sizeof(sockaddr);
sockfd = SD_LISTEN_FDS_START;
if (!getsockname(sockfd, &sockaddr, &sockaddr_sz))
sockname = strdup(sockaddr.sun_path);
}
#endif /* HAVE_LIBSYSTEMD */
#ifdef USE_GTK
@ -1660,7 +1670,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
/* This can create a thread that may call getenv, so it must follow
all calls to putenv and setenv. Also, this sets up
add_keyboard_wait_descriptor, which init_display uses. */
init_process_emacs (sockfd);
init_process_emacs (sockfd, sockname);
init_keyboard (); /* This too must precede init_sys_modes. */
if (!noninteractive)

View file

@ -4316,7 +4316,7 @@ extern void delete_keyboard_wait_descriptor (int);
extern void add_gpm_wait_descriptor (int);
extern void delete_gpm_wait_descriptor (int);
#endif
extern void init_process_emacs (int);
extern void init_process_emacs (int, char *);
extern void syms_of_process (void);
extern void setup_process_coding_systems (Lisp_Object);

View file

@ -276,6 +276,10 @@ static int max_desc;
the file descriptor of a socket that is already bound. */
static int external_sock_fd;
/* The name (path) of the socket that was passed to Emacs, when
`external_sock_fd' is not -1. */
static const char *external_sock_name = NULL;
/* Indexed by descriptor, gives the process (if any) for that descriptor. */
static Lisp_Object chan_process[FD_SETSIZE];
static void wait_for_socket_fds (Lisp_Object, char const *);
@ -7972,10 +7976,21 @@ restore_nofile_limit (void)
}
DEFUN ("get-external-sockname", Fget_external_sockname, Sget_external_sockname, 0, 0, 0,
doc: /* Return the path of an external socket passed to Emacs.
Otherwise return nil. */)
(void)
{
if (external_sock_name)
return make_string(external_sock_name, strlen(external_sock_name));
else
return Qnil;
}
/* This is not called "init_process" because that is the name of a
Mach system call, so it would cause problems on Darwin systems. */
void
init_process_emacs (int sockfd)
init_process_emacs (int sockfd, char *sockname)
{
#ifdef subprocesses
int i;
@ -8010,6 +8025,7 @@ init_process_emacs (int sockfd)
#endif
external_sock_fd = sockfd;
external_sock_name = sockname;
max_desc = -1;
memset (fd_callback_info, 0, sizeof (fd_callback_info));
@ -8304,4 +8320,5 @@ returns non-`nil'. */);
defsubr (&Sprocess_inherit_coding_system_flag);
defsubr (&Slist_system_processes);
defsubr (&Sprocess_attributes);
defsubr (&Sget_external_sockname);
}