#ifdef MSDOS
#include <binary-io.h>
+#include "dosfns.h"
+#endif
+
+#ifdef HAVE_LIBSYSTEMD
+# include <systemd/sd-daemon.h>
+# include <sys/socket.h>
#endif
#ifdef HAVE_WINDOW_SYSTEM
#include "systime.h"
#include "puresize.h"
+#include "getpagesize.h"
#include "gnutls.h"
#if (defined PROFILING \
bool do_initial_setlocale;
bool dumping;
int skip_args = 0;
-#ifdef HAVE_SETRLIMIT
- struct rlimit rlim;
-#endif
bool no_loadup = 0;
char *junk = 0;
char *dname_arg = 0;
is built with an 8MB stack. Moreover, the setrlimit call can
cause problems on Cygwin
(https://www.cygwin.com/ml/cygwin/2015-07/msg00096.html). */
- if (1
-#ifndef CANNOT_DUMP
- && (!noninteractive || initialized)
-#endif
- && !getrlimit (RLIMIT_STACK, &rlim))
+ struct rlimit rlim;
+ if (getrlimit (RLIMIT_STACK, &rlim) == 0
+ && 0 <= rlim.rlim_cur && rlim.rlim_cur <= LONG_MAX)
{
- long newlim;
- /* Approximate the amount regex.c needs per unit of re_max_failures. */
+ long lim = rlim.rlim_cur;
+
+ /* Approximate the amount regex.c needs per unit of
+ re_max_failures, then add 33% to cover the size of the
+ smaller stacks that regex.c successively allocates and
+ discards on its way to the maximum. */
int ratio = 20 * sizeof (char *);
- /* Then add 33% to cover the size of the smaller stacks that regex.c
- successively allocates and discards, on its way to the maximum. */
ratio += ratio / 3;
- /* Add in some extra to cover
- what we're likely to use for other reasons. */
- newlim = re_max_failures * ratio + 200000;
-#ifdef __NetBSD__
- /* NetBSD (at least NetBSD 1.2G and former) has a bug in its
- stack allocation routine for new process that the allocation
- fails if stack limit is not on page boundary. So, round up the
- new limit to page boundary. */
- newlim = (newlim + getpagesize () - 1) / getpagesize () * getpagesize ();
-#endif
- if (newlim > rlim.rlim_max)
+
+ /* Extra space to cover what we're likely to use for other reasons. */
+ int extra = 200000;
+
+ bool try_to_grow_stack = true;
+#ifndef CANNOT_DUMP
+ try_to_grow_stack = !noninteractive || initialized;
+#endif
+
+ if (try_to_grow_stack)
{
- newlim = rlim.rlim_max;
- /* Don't let regex.c overflow the stack we have. */
- re_max_failures = (newlim - 200000) / ratio;
+ long newlim = re_max_failures * ratio + extra;
+
+ /* Round the new limit to a page boundary; this is needed
+ for Darwin kernel 15.4.0 (see Bug#23622) and perhaps
+ other systems. Do not shrink the stack and do not exceed
+ rlim_max. Don't worry about exact values of
+ RLIM_INFINITY etc. since in practice when they are
+ nonnegative they are so large that the code does the
+ right thing anyway. */
+ long pagesize = getpagesize ();
+ newlim += pagesize - 1;
+ if (0 <= rlim.rlim_max && rlim.rlim_max < newlim)
+ newlim = rlim.rlim_max;
+ newlim -= newlim % pagesize;
+
+ if (pagesize <= newlim - lim)
+ {
+ rlim.rlim_cur = newlim;
+ if (setrlimit (RLIMIT_STACK, &rlim) == 0)
+ lim = newlim;
+ }
}
- if (rlim.rlim_cur < newlim)
- rlim.rlim_cur = newlim;
- setrlimit (RLIMIT_STACK, &rlim);
+ /* Don't let regex.c overflow the stack. */
+ re_max_failures = lim < extra ? 0 : min (lim - extra, SIZE_MAX) / ratio;
}
#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */
w32_daemon_event = NULL;
#endif
+
+ int sockfd = -1;
+
if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
|| argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args))
{
exit (1);
}
+#ifdef HAVE_LIBSYSTEMD
+ /* Read the number of sockets passed through by systemd. */
+ int systemd_socket = sd_listen_fds (1);
+
+ if (systemd_socket > 1)
+ fprintf (stderr,
+ ("\n"
+ "Warning: systemd passed more than one socket to Emacs.\n"
+ "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;
+#endif /* HAVE_LIBSYSTEMD */
+
#ifndef DAEMON_MUST_EXEC
#ifdef USE_GTK
fprintf (stderr, "\nWarning: due to a long standing Gtk+ bug\nhttp://bugzilla.gnome.org/show_bug.cgi?id=85715\n\
/* 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 ();
+ init_process_emacs (sockfd);
init_keyboard (); /* This too must precede init_sys_modes. */
if (!noninteractive)