Support daemon mode on MS-Windows (bug#19688)
src/emacs.c <w32_daemon_event> [WINDOWSNT]: New global var. (main) [WINDOWSNT]: Initialize it to NULL. Create the event to signal clients we are ready for connections. (Fdaemon_initialized): Use DAEMON_RUNNING. [WINDOWSNT]: MS-Windows specific code to signal clients we are ready for connections. src/lisp.h (DAEMON_RUNNING): New macro, encapsulates Posix and MS-Windows conditions for running in daemon mode. src/minibuf.c (read_minibuf): Use DAEMON_RUNNING. src/keyboard.c (kbd_buffer_get_event): Use DAEMON_RUNNING. src/dispnew.c (init_display) [WINDOWSNT]: Initialize frames/terminal even in daemon mode. nt/inc/ms-w32.h (W32_DAEMON_EVENT): New macro. lib-src/emacsclient.c (decode_options) [WINDOWSNT]: Don't reject empty arguments for --alternate-editor. (print_help_and_exit) [WINDOWSNT]: Don't refrain from advertising empty arguments for --alternate-editor. (start_daemon_and_retry_set_socket) [WINDOWSNT]: MS-Windows specific code to start Emacs in daemon mode and wait for it to be ready for client connections. lisp/server.el (server-process-filter): Force GUI frames on MS-Windows in daemon mode, even if a TTY frame was requested. lisp/frameset.el (frameset-keep-original-display-p): Don't assume windows-nt cannot be in daemon mode. lisp/frame.el (window-system-for-display): Don't assume windows-nt cannot be in daemon mode.
This commit is contained in:
parent
6ef14349fa
commit
805fe50708
14 changed files with 179 additions and 26 deletions
|
@ -1,3 +1,14 @@
|
|||
2015-02-27 Mark Laws <mdl@60hz.org>
|
||||
|
||||
Support daemon mode on MS-Windows (bug#19688)
|
||||
* emacsclient.c (decode_options) [WINDOWSNT]: Don't reject empty
|
||||
arguments for --alternate-editor.
|
||||
(print_help_and_exit) [WINDOWSNT]: Don't refrain from advertising
|
||||
empty arguments for --alternate-editor.
|
||||
(start_daemon_and_retry_set_socket) [WINDOWSNT]: MS-Windows
|
||||
specific code to start Emacs in daemon mode and wait for it to be
|
||||
ready for client connections.
|
||||
|
||||
2015-02-23 Pete Williamson <petewil0@googlemail.com> (tiny change)
|
||||
|
||||
Use ${EXEEXT} more uniformly in makefiles
|
||||
|
|
|
@ -595,13 +595,6 @@ decode_options (int argc, char **argv)
|
|||
display = NULL;
|
||||
tty = 1;
|
||||
}
|
||||
|
||||
if (alternate_editor && alternate_editor[0] == '\0')
|
||||
{
|
||||
message (true, "--alternate-editor argument or ALTERNATE_EDITOR variable cannot be\n\
|
||||
an empty string");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif /* WINDOWSNT */
|
||||
}
|
||||
|
||||
|
@ -642,10 +635,8 @@ The following OPTIONS are accepted:\n\
|
|||
Set filename of the TCP authentication file\n\
|
||||
-a EDITOR, --alternate-editor=EDITOR\n\
|
||||
Editor to fallback to if the server is not running\n"
|
||||
#ifndef WINDOWSNT
|
||||
" If EDITOR is the empty string, start Emacs in daemon\n\
|
||||
mode and try connecting again\n"
|
||||
#endif /* not WINDOWSNT */
|
||||
"\n\
|
||||
Report bugs with M-x report-emacs-bug.\n");
|
||||
exit (EXIT_SUCCESS);
|
||||
|
@ -1511,7 +1502,77 @@ start_daemon_and_retry_set_socket (void)
|
|||
execvp ("emacs", d_argv);
|
||||
message (true, "%s: error starting emacs daemon\n", progname);
|
||||
}
|
||||
#endif /* WINDOWSNT */
|
||||
#else /* WINDOWSNT */
|
||||
DWORD wait_result;
|
||||
HANDLE w32_daemon_event;
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ZeroMemory (&si, sizeof si);
|
||||
si.cb = sizeof si;
|
||||
ZeroMemory (&pi, sizeof pi);
|
||||
|
||||
/* We start Emacs in daemon mode, and then wait for it to signal us
|
||||
it is ready to accept client connections, by asserting an event
|
||||
whose name is known to the daemon (defined by nt/inc/ms-w32.h). */
|
||||
|
||||
if (!CreateProcess (NULL, "emacs --daemon", NULL, NULL, FALSE,
|
||||
CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
|
||||
{
|
||||
char* msg = NULL;
|
||||
|
||||
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
NULL, GetLastError (), 0, (LPTSTR)&msg, 0, NULL);
|
||||
message (true, "%s: error starting emacs daemon (%s)\n", progname, msg);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
w32_daemon_event = CreateEvent (NULL, TRUE, FALSE, W32_DAEMON_EVENT);
|
||||
if (w32_daemon_event == NULL)
|
||||
{
|
||||
message (true, "Couldn't create Windows daemon event");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
if ((wait_result = WaitForSingleObject (w32_daemon_event, INFINITE))
|
||||
!= WAIT_OBJECT_0)
|
||||
{
|
||||
char *msg = NULL;
|
||||
|
||||
switch (wait_result)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
msg = "The daemon exited unexpectedly";
|
||||
break;
|
||||
case WAIT_TIMEOUT:
|
||||
/* Can't happen due to INFINITE. */
|
||||
default:
|
||||
case WAIT_FAILED:
|
||||
FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
||||
| FORMAT_MESSAGE_ALLOCATE_BUFFER
|
||||
| FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
||||
NULL, GetLastError (), 0, (LPTSTR)&msg, 0, NULL);
|
||||
break;
|
||||
}
|
||||
message (true, "Error: Could not start the Emacs daemon: %s\n", msg);
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
CloseHandle (w32_daemon_event);
|
||||
|
||||
/* Try connecting, the daemon should have started by now. */
|
||||
/* It's just a progress message, so don't pop a dialog if this is
|
||||
emacsclientw. */
|
||||
if (!w32_window_app ())
|
||||
message (true,
|
||||
"Emacs daemon should have started, trying to connect again\n");
|
||||
if ((emacs_socket = set_socket (1)) == INVALID_SOCKET)
|
||||
{
|
||||
message (true,
|
||||
"Error: Cannot connect even after starting the Emacs daemon\n");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
#endif /* WINDOWSNT */
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2015-02-27 Mark Laws <mdl@60hz.org>
|
||||
|
||||
Support daemon mode on MS-Windows (bug#19688)
|
||||
* server.el (server-process-filter): Force GUI frames on
|
||||
MS-Windows in daemon mode, even if a TTY frame was requested.
|
||||
|
||||
* frameset.el (frameset-keep-original-display-p): Don't assume
|
||||
windows-nt cannot be in daemon mode.
|
||||
|
||||
* frame.el (window-system-for-display): Don't assume windows-nt
|
||||
cannot be in daemon mode.
|
||||
|
||||
2015-02-26 Ivan Shmakov <ivan@siamics.net>
|
||||
|
||||
* faces.el (face-list-p): Split from face-at-point.
|
||||
|
|
|
@ -546,7 +546,8 @@ is not considered (see `next-frame')."
|
|||
Return nil if we don't know how to interpret DISPLAY."
|
||||
;; MS-Windows doesn't know how to create a GUI frame in a -nw session.
|
||||
(if (and (eq system-type 'windows-nt)
|
||||
(null (window-system)))
|
||||
(null (window-system))
|
||||
(not (daemonp)))
|
||||
nil
|
||||
(cl-loop for descriptor in display-format-alist
|
||||
for pattern = (car descriptor)
|
||||
|
|
|
@ -1022,8 +1022,8 @@ Internal use only."
|
|||
(defun frameset-keep-original-display-p (force-display)
|
||||
"True if saved frames' displays should be honored.
|
||||
For the meaning of FORCE-DISPLAY, see `frameset-restore'."
|
||||
(cond ((daemonp) t)
|
||||
((eq system-type 'windows-nt) nil) ;; Does ns support more than one display?
|
||||
(cond ((eq system-type 'windows-nt) nil) ;; Does ns support more than one display?
|
||||
((daemonp) t)
|
||||
(t (not force-display))))
|
||||
|
||||
(defun frameset-minibufferless-first-p (frame1 _frame2)
|
||||
|
|
|
@ -1139,9 +1139,12 @@ The following commands are accepted by the client:
|
|||
;; frame. If running a GUI server, force the frame
|
||||
;; type to GUI. (Cygwin is perfectly happy with
|
||||
;; multi-tty support, so don't override the user's
|
||||
;; choice there.)
|
||||
;; choice there.) In daemon mode on Windows, we can't
|
||||
;; make tty frames, so force the frame type to GUI
|
||||
;; there too.
|
||||
(when (and (eq system-type 'windows-nt)
|
||||
(eq window-system 'w32))
|
||||
(or (daemonp)
|
||||
(eq window-system 'w32)))
|
||||
(push "-window-system" args-left)))
|
||||
|
||||
;; -position LINE[:COLUMN]: Set point to the given
|
||||
|
@ -1215,7 +1218,10 @@ The following commands are accepted by the client:
|
|||
terminal-frame)))))
|
||||
(setq tty-name nil tty-type nil)
|
||||
(if display (server-select-display display)))
|
||||
((eq tty-name 'window-system)
|
||||
((or (and (eq system-type 'windows-nt)
|
||||
(daemonp)
|
||||
(setq display "w32"))
|
||||
(eq tty-name 'window-system))
|
||||
(server-create-window-system-frame display nowait proc
|
||||
parent-id
|
||||
frame-parameters))
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2015-02-27 Mark Laws <mdl@60hz.org>
|
||||
|
||||
Support daemon mode on MS-Windows (bug#19688)
|
||||
* inc/ms-w32.h (W32_DAEMON_EVENT): New macro.
|
||||
|
||||
2015-01-16 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* Makefile.in (AM_V_CC, am__v_CC_, am__v_CC_0, am__v_CC_1)
|
||||
|
|
|
@ -597,5 +597,7 @@ extern void _DebPrint (const char *fmt, ...);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* Event name for when emacsclient starts the Emacs daemon on Windows. */
|
||||
#define W32_DAEMON_EVENT "EmacsServerEvent"
|
||||
|
||||
/* ============================================================ */
|
||||
|
|
|
@ -1,3 +1,23 @@
|
|||
2015-02-27 Mark Laws <mdl@60hz.org>
|
||||
|
||||
Support daemon mode on MS-Windows (bug#19688)
|
||||
* emacs.c <w32_daemon_event> [WINDOWSNT]: New global var.
|
||||
(main) [WINDOWSNT]: Initialize it to NULL. Create the event to
|
||||
signal clients we are ready for connections.
|
||||
(Fdaemon_initialized): Use DAEMON_RUNNING.
|
||||
[WINDOWSNT]: MS-Windows specific code to signal clients we are
|
||||
ready for connections.
|
||||
|
||||
* lisp.h (DAEMON_RUNNING): New macro, encapsulates Posix and
|
||||
MS-Windows conditions for running in daemon mode.
|
||||
|
||||
* minibuf.c (read_minibuf): Use DAEMON_RUNNING.
|
||||
|
||||
* keyboard.c (kbd_buffer_get_event): Use DAEMON_RUNNING.
|
||||
|
||||
* dispnew.c (init_display) [WINDOWSNT]: Initialize frames/terminal
|
||||
even in daemon mode.
|
||||
|
||||
2015-02-26 Jan Djärv <jan.h.d@swipnet.se>
|
||||
|
||||
* xmenu.c (create_and_show_popup_menu): Call XTranslateCoordinates,
|
||||
|
|
|
@ -5949,9 +5949,12 @@ init_display (void)
|
|||
}
|
||||
#endif /* SIGWINCH */
|
||||
|
||||
/* If running as a daemon, no need to initialize any frames/terminal. */
|
||||
/* If running as a daemon, no need to initialize any frames/terminal,
|
||||
except on Windows, where we at least want to initialize it. */
|
||||
#ifndef WINDOWSNT
|
||||
if (IS_DAEMON)
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* If the user wants to use a window system, we shouldn't bother
|
||||
initializing the terminal. This is especially important when the
|
||||
|
|
37
src/emacs.c
37
src/emacs.c
|
@ -195,9 +195,13 @@ bool no_site_lisp;
|
|||
/* Name for the server started by the daemon.*/
|
||||
static char *daemon_name;
|
||||
|
||||
#ifndef WINDOWSNT
|
||||
/* Pipe used to send exit notification to the daemon parent at
|
||||
startup. */
|
||||
int daemon_pipe[2];
|
||||
#else
|
||||
HANDLE w32_daemon_event;
|
||||
#endif
|
||||
|
||||
/* Save argv and argc. */
|
||||
char **initial_argv;
|
||||
|
@ -982,8 +986,12 @@ main (int argc, char **argv)
|
|||
exit (0);
|
||||
}
|
||||
|
||||
#ifndef WINDOWSNT
|
||||
/* Make sure IS_DAEMON starts up as false. */
|
||||
daemon_pipe[1] = 0;
|
||||
#else
|
||||
w32_daemon_event = NULL;
|
||||
#endif
|
||||
|
||||
if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
|
||||
|| argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args))
|
||||
|
@ -1107,16 +1115,25 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
}
|
||||
#endif /* DAEMON_MUST_EXEC */
|
||||
|
||||
if (dname_arg)
|
||||
daemon_name = xstrdup (dname_arg);
|
||||
/* Close unused reading end of the pipe. */
|
||||
emacs_close (daemon_pipe[0]);
|
||||
|
||||
setsid ();
|
||||
#else /* DOS_NT */
|
||||
#elif defined(WINDOWSNT)
|
||||
/* Indicate that we want daemon mode. */
|
||||
w32_daemon_event = CreateEvent (NULL, TRUE, FALSE, W32_DAEMON_EVENT);
|
||||
if (w32_daemon_event == NULL)
|
||||
{
|
||||
fprintf (stderr, "Couldn't create MS-Windows event for daemon: %s\n",
|
||||
w32_strerror (0));
|
||||
exit (1);
|
||||
}
|
||||
#else /* MSDOS */
|
||||
fprintf (stderr, "This platform does not support the -daemon flag.\n");
|
||||
exit (1);
|
||||
#endif /* DOS_NT */
|
||||
#endif /* MSDOS */
|
||||
if (dname_arg)
|
||||
daemon_name = xstrdup (dname_arg);
|
||||
}
|
||||
|
||||
#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \
|
||||
|
@ -2313,17 +2330,18 @@ This finishes the daemonization process by doing the other half of detaching
|
|||
from the parent process and its tty file descriptors. */)
|
||||
(void)
|
||||
{
|
||||
int nfd;
|
||||
bool err = 0;
|
||||
|
||||
if (!IS_DAEMON)
|
||||
error ("This function can only be called if emacs is run as a daemon");
|
||||
|
||||
if (daemon_pipe[1] < 0)
|
||||
if (!DAEMON_RUNNING)
|
||||
error ("The daemon has already been initialized");
|
||||
|
||||
if (NILP (Vafter_init_time))
|
||||
error ("This function can only be called after loading the init files");
|
||||
#ifndef WINDOWSNT
|
||||
int nfd;
|
||||
|
||||
/* Get rid of stdin, stdout and stderr. */
|
||||
nfd = emacs_open ("/dev/null", O_RDWR, 0);
|
||||
|
@ -2344,6 +2362,13 @@ from the parent process and its tty file descriptors. */)
|
|||
err |= emacs_close (daemon_pipe[1]) != 0;
|
||||
/* Set it to an invalid value so we know we've already run this function. */
|
||||
daemon_pipe[1] = -1;
|
||||
#else /* WINDOWSNT */
|
||||
/* Signal the waiting emacsclient process. */
|
||||
err |= SetEvent (w32_daemon_event) == 0;
|
||||
err |= CloseHandle (w32_daemon_event) == 0;
|
||||
/* Set it to an invalid value so we know we've already run this function. */
|
||||
w32_daemon_event = INVALID_HANDLE_VALUE;
|
||||
#endif
|
||||
|
||||
if (err)
|
||||
error ("I/O error during daemon initialization");
|
||||
|
|
|
@ -3853,7 +3853,7 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
if (noninteractive
|
||||
/* In case we are running as a daemon, only do this before
|
||||
detaching from the terminal. */
|
||||
|| (IS_DAEMON && daemon_pipe[1] >= 0))
|
||||
|| (IS_DAEMON && DAEMON_RUNNING))
|
||||
{
|
||||
int c = getchar ();
|
||||
XSETINT (obj, c);
|
||||
|
|
|
@ -4222,9 +4222,16 @@ extern bool noninteractive;
|
|||
extern bool no_site_lisp;
|
||||
|
||||
/* Pipe used to send exit notification to the daemon parent at
|
||||
startup. */
|
||||
startup. On Windows, we use a kernel event instead. */
|
||||
#ifndef WINDOWSNT
|
||||
extern int daemon_pipe[2];
|
||||
#define IS_DAEMON (daemon_pipe[1] != 0)
|
||||
#define DAEMON_RUNNING (daemon_pipe[1] >= 0)
|
||||
#else /* WINDOWSNT */
|
||||
extern void *w32_daemon_event;
|
||||
#define IS_DAEMON (w32_daemon_event != NULL)
|
||||
#define DAEMON_RUNNING (w32_daemon_event != INVALID_HANDLE_VALUE)
|
||||
#endif
|
||||
|
||||
/* True if handling a fatal error already. */
|
||||
extern bool fatal_error_in_progress;
|
||||
|
|
|
@ -459,7 +459,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
|
|||
if ((noninteractive
|
||||
/* In case we are running as a daemon, only do this before
|
||||
detaching from the terminal. */
|
||||
|| (IS_DAEMON && (daemon_pipe[1] >= 0)))
|
||||
|| (IS_DAEMON && DAEMON_RUNNING))
|
||||
&& NILP (Vexecuting_kbd_macro))
|
||||
{
|
||||
val = read_minibuf_noninteractive (map, initial, prompt,
|
||||
|
|
Loading…
Add table
Reference in a new issue