diff options
| author | Matthew Leach | 2016-04-16 12:43:01 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2016-04-16 12:43:01 +0300 |
| commit | e390b7b54651d3c5a4c36168e84e96e197631f41 (patch) | |
| tree | d4ccdf1d6e243e9a5f58b42e78de349a1ffbc6c2 /src | |
| parent | bb8c8fdfbb226ea760e8e5761ecda98c8cd9564f (diff) | |
| download | emacs-e390b7b54651d3c5a4c36168e84e96e197631f41.tar.gz emacs-e390b7b54651d3c5a4c36168e84e96e197631f41.zip | |
Add external socket launching support
* src/process.c (connect_network_socket): Allow a pre-allocated socket
descriptor to be used if passed to Emacs, avoiding the call to
'socket' and 'bind'.
(Fmake_network_process): Allow users to pass ':use-external-socket' in
the parameter plist to use any sockets that have been passed to Emacs.
(wait_reading_process_output): Call 'socket' and 'bind' every time.
(syms_of_process): New symbol ':use-external-socket'.
(set_external_socket_descriptor): New function.
(external_sock_fd): New variable.
* src/lisp.h: (set_external_socket_descriptor): New declaration.
* src/emacs.c (main): Call 'sd_listen_fds' to read the number of sockets
passed and call 'set_external_socket_descriptor' to set the external
socket.
* src/Makefile.in: Add libsystemd library and C flags to the Emacs
compilation options.
* configure.ac: Add new default-on option "systemd" and check for
libsystemd at configure time.
* lisp/server.el (server-start): Set ':use-external-socket' to 't' when
calling 'make-network-process'.
* etc/NEWS: Document new socket-passing functionality and the configure
option to disable systemd interaction.
* doc/emacs/misc.texi (Emacs Server): Document systemd socket passing
functionality and provide systemd unit examples.
* doc/lispref/processes.texi (Network Processes): Document new
'make-network-process' option ':use-external-socket'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 6 | ||||
| -rw-r--r-- | src/emacs.c | 22 | ||||
| -rw-r--r-- | src/lisp.h | 1 | ||||
| -rw-r--r-- | src/process.c | 52 |
4 files changed, 73 insertions, 8 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index c290a6082da..fc9360a5bde 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -307,6 +307,9 @@ LIBSELINUX_LIBS = @LIBSELINUX_LIBS@ | |||
| 307 | LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ | 307 | LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@ |
| 308 | LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ | 308 | LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@ |
| 309 | 309 | ||
| 310 | LIBSYSTEMD_LIBS = @LIBSYSTEMD_LIBS@ | ||
| 311 | LIBSYSTEMD_CFLAGS = @LIBSYSTEMD_CFLAGS@ | ||
| 312 | |||
| 310 | INTERVALS_H = dispextern.h intervals.h composite.h | 313 | INTERVALS_H = dispextern.h intervals.h composite.h |
| 311 | 314 | ||
| 312 | GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ | 315 | GETLOADAVG_LIBS = @GETLOADAVG_LIBS@ |
| @@ -372,6 +375,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \ | |||
| 372 | $(WEBKIT_CFLAGS) \ | 375 | $(WEBKIT_CFLAGS) \ |
| 373 | $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ | 376 | $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ |
| 374 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ | 377 | $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ |
| 378 | $(LIBSYSTEMD_CFLAGS) \ | ||
| 375 | $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ | 379 | $(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \ |
| 376 | $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS) | 380 | $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS) |
| 377 | ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) | 381 | ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) |
| @@ -489,7 +493,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \ | |||
| 489 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ | 493 | $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ |
| 490 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ | 494 | $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ |
| 491 | $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) \ | 495 | $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) \ |
| 492 | $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) | 496 | $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) |
| 493 | 497 | ||
| 494 | $(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT) | 498 | $(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT) |
| 495 | $(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)" | 499 | $(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)" |
diff --git a/src/emacs.c b/src/emacs.c index c21c9e3971c..a51df0903b1 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -56,6 +56,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 56 | #include <binary-io.h> | 56 | #include <binary-io.h> |
| 57 | #endif | 57 | #endif |
| 58 | 58 | ||
| 59 | #ifdef HAVE_LIBSYSTEMD | ||
| 60 | #include <systemd/sd-daemon.h> | ||
| 61 | #include <sys/socket.h> | ||
| 62 | #endif /* HAVE_LIBSYSTEMD */ | ||
| 63 | |||
| 59 | #ifdef HAVE_WINDOW_SYSTEM | 64 | #ifdef HAVE_WINDOW_SYSTEM |
| 60 | #include TERM_HEADER | 65 | #include TERM_HEADER |
| 61 | #endif /* HAVE_WINDOW_SYSTEM */ | 66 | #endif /* HAVE_WINDOW_SYSTEM */ |
| @@ -676,6 +681,9 @@ main (int argc, char **argv) | |||
| 676 | char dname_arg2[80]; | 681 | char dname_arg2[80]; |
| 677 | #endif | 682 | #endif |
| 678 | char *ch_to_dir = 0; | 683 | char *ch_to_dir = 0; |
| 684 | #ifdef HAVE_LIBSYSTEMD | ||
| 685 | int systemd_socket; | ||
| 686 | #endif | ||
| 679 | 687 | ||
| 680 | /* If we use --chdir, this records the original directory. */ | 688 | /* If we use --chdir, this records the original directory. */ |
| 681 | char *original_pwd = 0; | 689 | char *original_pwd = 0; |
| @@ -999,6 +1007,20 @@ main (int argc, char **argv) | |||
| 999 | exit (1); | 1007 | exit (1); |
| 1000 | } | 1008 | } |
| 1001 | 1009 | ||
| 1010 | #ifdef HAVE_LIBSYSTEMD | ||
| 1011 | /* Read the number of sockets passed through by systemd. */ | ||
| 1012 | systemd_socket = sd_listen_fds(1); | ||
| 1013 | |||
| 1014 | if (systemd_socket > 1) | ||
| 1015 | fprintf (stderr, "\nWarning: systemd has passed more than one socket to the Emacs process.\n\ | ||
| 1016 | Try adding 'Accept=false' in the Emacs socket unit file.\n"); | ||
| 1017 | |||
| 1018 | else if (systemd_socket == 1 && | ||
| 1019 | sd_is_socket (SD_LISTEN_FDS_START, | ||
| 1020 | AF_UNSPEC, SOCK_STREAM, 1) >= 0) | ||
| 1021 | set_external_socket_descriptor (SD_LISTEN_FDS_START); | ||
| 1022 | #endif /* HAVE_LIBSYSTEMD */ | ||
| 1023 | |||
| 1002 | #ifndef DAEMON_MUST_EXEC | 1024 | #ifndef DAEMON_MUST_EXEC |
| 1003 | #ifdef USE_GTK | 1025 | #ifdef USE_GTK |
| 1004 | fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\ | 1026 | fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\ |
diff --git a/src/lisp.h b/src/lisp.h index d111a78f3e0..c6f8bb89a3f 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4184,6 +4184,7 @@ extern void delete_gpm_wait_descriptor (int); | |||
| 4184 | extern void init_process_emacs (void); | 4184 | extern void init_process_emacs (void); |
| 4185 | extern void syms_of_process (void); | 4185 | extern void syms_of_process (void); |
| 4186 | extern void setup_process_coding_systems (Lisp_Object); | 4186 | extern void setup_process_coding_systems (Lisp_Object); |
| 4187 | extern void set_external_socket_descriptor (int); | ||
| 4187 | 4188 | ||
| 4188 | /* Defined in callproc.c. */ | 4189 | /* Defined in callproc.c. */ |
| 4189 | #ifndef DOS_NT | 4190 | #ifndef DOS_NT |
diff --git a/src/process.c b/src/process.c index a006ca61ac5..2dfad669072 100644 --- a/src/process.c +++ b/src/process.c | |||
| @@ -267,6 +267,9 @@ static int max_process_desc; | |||
| 267 | /* The largest descriptor currently in use for input; -1 if none. */ | 267 | /* The largest descriptor currently in use for input; -1 if none. */ |
| 268 | static int max_input_desc; | 268 | static int max_input_desc; |
| 269 | 269 | ||
| 270 | /* The descriptor of any sockets passed to Emacs; -1 if none. */ | ||
| 271 | static int external_sock_fd = -1; | ||
| 272 | |||
| 270 | /* Indexed by descriptor, gives the process (if any) for that descriptor. */ | 273 | /* Indexed by descriptor, gives the process (if any) for that descriptor. */ |
| 271 | static Lisp_Object chan_process[FD_SETSIZE]; | 274 | static Lisp_Object chan_process[FD_SETSIZE]; |
| 272 | static void wait_for_socket_fds (Lisp_Object, char const *); | 275 | static void wait_for_socket_fds (Lisp_Object, char const *); |
| @@ -3075,7 +3078,8 @@ finish_after_tls_connection (Lisp_Object proc) | |||
| 3075 | #endif | 3078 | #endif |
| 3076 | 3079 | ||
| 3077 | static void | 3080 | static void |
| 3078 | connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | 3081 | connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses, |
| 3082 | Lisp_Object use_external_socket_p) | ||
| 3079 | { | 3083 | { |
| 3080 | ptrdiff_t count = SPECPDL_INDEX (); | 3084 | ptrdiff_t count = SPECPDL_INDEX (); |
| 3081 | ptrdiff_t count1; | 3085 | ptrdiff_t count1; |
| @@ -3089,6 +3093,16 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | |||
| 3089 | struct Lisp_Process *p = XPROCESS (proc); | 3093 | struct Lisp_Process *p = XPROCESS (proc); |
| 3090 | Lisp_Object contact = p->childp; | 3094 | Lisp_Object contact = p->childp; |
| 3091 | int optbits = 0; | 3095 | int optbits = 0; |
| 3096 | int socket_to_use = -1; | ||
| 3097 | |||
| 3098 | if (!NILP (use_external_socket_p)) | ||
| 3099 | { | ||
| 3100 | socket_to_use = external_sock_fd; | ||
| 3101 | |||
| 3102 | /* Ensure we don't consume the external socket twice. */ | ||
| 3103 | external_sock_fd = -1; | ||
| 3104 | } | ||
| 3105 | |||
| 3092 | 3106 | ||
| 3093 | /* Do this in case we never enter the while-loop below. */ | 3107 | /* Do this in case we never enter the while-loop below. */ |
| 3094 | count1 = SPECPDL_INDEX (); | 3108 | count1 = SPECPDL_INDEX (); |
| @@ -3109,7 +3123,11 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | |||
| 3109 | sa = xmalloc (addrlen); | 3123 | sa = xmalloc (addrlen); |
| 3110 | conv_lisp_to_sockaddr (family, ip_address, sa, addrlen); | 3124 | conv_lisp_to_sockaddr (family, ip_address, sa, addrlen); |
| 3111 | 3125 | ||
| 3112 | s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol); | 3126 | if (socket_to_use != -1) |
| 3127 | s = socket_to_use; | ||
| 3128 | else | ||
| 3129 | s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol); | ||
| 3130 | |||
| 3113 | if (s < 0) | 3131 | if (s < 0) |
| 3114 | { | 3132 | { |
| 3115 | xerrno = errno; | 3133 | xerrno = errno; |
| @@ -3168,8 +3186,11 @@ connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) | |||
| 3168 | report_file_error ("Cannot set reuse option on server socket", Qnil); | 3186 | report_file_error ("Cannot set reuse option on server socket", Qnil); |
| 3169 | } | 3187 | } |
| 3170 | 3188 | ||
| 3171 | if (bind (s, sa, addrlen)) | 3189 | /* If we are passed a socket descriptor, it should be |
| 3172 | report_file_error ("Cannot bind server socket", Qnil); | 3190 | already bound. */ |
| 3191 | if (socket_to_use == -1) | ||
| 3192 | if (bind (s, sa, addrlen)) | ||
| 3193 | report_file_error ("Cannot bind server socket", Qnil); | ||
| 3173 | 3194 | ||
| 3174 | #ifdef HAVE_GETSOCKNAME | 3195 | #ifdef HAVE_GETSOCKNAME |
| 3175 | if (p->port == 0) | 3196 | if (p->port == 0) |
| @@ -3534,6 +3555,11 @@ The following network options can be specified for this connection: | |||
| 3534 | (this is allowed by default for a server process). | 3555 | (this is allowed by default for a server process). |
| 3535 | :bindtodevice NAME -- bind to interface NAME. Using this may require | 3556 | :bindtodevice NAME -- bind to interface NAME. Using this may require |
| 3536 | special privileges on some systems. | 3557 | special privileges on some systems. |
| 3558 | :use-external-socket BOOL -- Use any pre-allocated sockets that have | ||
| 3559 | been passed to Emacs. If Emacs wasn't | ||
| 3560 | passed a socket, this option is silently | ||
| 3561 | ignored. | ||
| 3562 | |||
| 3537 | 3563 | ||
| 3538 | Consult the relevant system programmer's manual pages for more | 3564 | Consult the relevant system programmer's manual pages for more |
| 3539 | information on using these options. | 3565 | information on using these options. |
| @@ -3578,7 +3604,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3578 | EMACS_INT port = 0; | 3604 | EMACS_INT port = 0; |
| 3579 | Lisp_Object tem; | 3605 | Lisp_Object tem; |
| 3580 | Lisp_Object name, buffer, host, service, address; | 3606 | Lisp_Object name, buffer, host, service, address; |
| 3581 | Lisp_Object filter, sentinel; | 3607 | Lisp_Object filter, sentinel, use_external_socket_p; |
| 3582 | Lisp_Object ip_addresses = Qnil; | 3608 | Lisp_Object ip_addresses = Qnil; |
| 3583 | int socktype; | 3609 | int socktype; |
| 3584 | int family = -1; | 3610 | int family = -1; |
| @@ -3618,6 +3644,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3618 | buffer = Fplist_get (contact, QCbuffer); | 3644 | buffer = Fplist_get (contact, QCbuffer); |
| 3619 | filter = Fplist_get (contact, QCfilter); | 3645 | filter = Fplist_get (contact, QCfilter); |
| 3620 | sentinel = Fplist_get (contact, QCsentinel); | 3646 | sentinel = Fplist_get (contact, QCsentinel); |
| 3647 | use_external_socket_p = Fplist_get (contact, QCuse_external_socket); | ||
| 3621 | 3648 | ||
| 3622 | CHECK_STRING (name); | 3649 | CHECK_STRING (name); |
| 3623 | 3650 | ||
| @@ -3914,7 +3941,7 @@ usage: (make-network-process &rest ARGS) */) | |||
| 3914 | } | 3941 | } |
| 3915 | #endif | 3942 | #endif |
| 3916 | 3943 | ||
| 3917 | connect_network_socket (proc, ip_addresses); | 3944 | connect_network_socket (proc, ip_addresses, use_external_socket_p); |
| 3918 | return proc; | 3945 | return proc; |
| 3919 | } | 3946 | } |
| 3920 | 3947 | ||
| @@ -4848,7 +4875,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, | |||
| 4848 | { | 4875 | { |
| 4849 | Lisp_Object ip_addresses = check_for_dns (aproc); | 4876 | Lisp_Object ip_addresses = check_for_dns (aproc); |
| 4850 | if (!NILP (ip_addresses) && !EQ (ip_addresses, Qt)) | 4877 | if (!NILP (ip_addresses) && !EQ (ip_addresses, Qt)) |
| 4851 | connect_network_socket (aproc, ip_addresses); | 4878 | connect_network_socket (aproc, ip_addresses, Qnil); |
| 4852 | else | 4879 | else |
| 4853 | retry_for_async = true; | 4880 | retry_for_async = true; |
| 4854 | } | 4881 | } |
| @@ -7709,6 +7736,16 @@ catch_child_signal (void) | |||
| 7709 | } | 7736 | } |
| 7710 | #endif /* subprocesses */ | 7737 | #endif /* subprocesses */ |
| 7711 | 7738 | ||
| 7739 | /* Set the external socket descriptor for Emacs to use when | ||
| 7740 | `make-network-process' is called with a non-nil | ||
| 7741 | `:use-external-socket' option. The fd should have been checked to | ||
| 7742 | ensure it is a valid socket and is already bound. */ | ||
| 7743 | void | ||
| 7744 | set_external_socket_descriptor(int fd) | ||
| 7745 | { | ||
| 7746 | external_sock_fd = fd; | ||
| 7747 | } | ||
| 7748 | |||
| 7712 | 7749 | ||
| 7713 | /* This is not called "init_process" because that is the name of a | 7750 | /* This is not called "init_process" because that is the name of a |
| 7714 | Mach system call, so it would cause problems on Darwin systems. */ | 7751 | Mach system call, so it would cause problems on Darwin systems. */ |
| @@ -7837,6 +7874,7 @@ syms_of_process (void) | |||
| 7837 | DEFSYM (QCserver, ":server"); | 7874 | DEFSYM (QCserver, ":server"); |
| 7838 | DEFSYM (QCnowait, ":nowait"); | 7875 | DEFSYM (QCnowait, ":nowait"); |
| 7839 | DEFSYM (QCsentinel, ":sentinel"); | 7876 | DEFSYM (QCsentinel, ":sentinel"); |
| 7877 | DEFSYM (QCuse_external_socket, ":use-external-socket"); | ||
| 7840 | DEFSYM (QCtls_parameters, ":tls-parameters"); | 7878 | DEFSYM (QCtls_parameters, ":tls-parameters"); |
| 7841 | DEFSYM (Qnsm_verify_connection, "nsm-verify-connection"); | 7879 | DEFSYM (Qnsm_verify_connection, "nsm-verify-connection"); |
| 7842 | DEFSYM (QClog, ":log"); | 7880 | DEFSYM (QClog, ":log"); |