diff --git a/src/configure.in b/src/configure.in
index 03f08ac1151c94630ac50e26d0250326429cf195..cb9c5fa8bd586631bfd9b34b33db7296a2736ef4 100644
--- a/src/configure.in
+++ b/src/configure.in
@@ -4510,6 +4510,7 @@ fi
 AC_CHECK_FUNCS( \
  _crypt \
  poll \
+ accept4 \
  closefrom \
  crypt \
  fdwalk \
diff --git a/src/fd_control.c b/src/fd_control.c
index 90ac7acee555444d89d7401b4b3c2d824bb4b87f..2e9295657ff98bb5cb8f3a8be1afc041baf8d917 100644
--- a/src/fd_control.c
+++ b/src/fd_control.c
@@ -224,6 +224,22 @@ PMOD_EXPORT int set_close_on_exec(int fd, int which)
 #endif /* !HAVE_BROKEN_F_SETFD */
 }
 
+#ifndef HAVE_ACCEPT4
+int accept4(int fd, struct sockaddr *addr, ACCEPT_SIZE_T *addrlen, int flags)
+{
+  int fd = fd_accept(fd, addr, addrlen);
+  if (!flags || (fd < 0)) return fd;
+  if (((flags & SOCK_NONBLOCK) && (set_nonblocking(fd, 1) < 0)) ||
+      ((flags & SOCK_CLOEXEC) && (set_close_on_exec(fd, 1) < 0))) {
+    int e = errno;
+    fd_close(fd);
+    errno = e;
+    return -1;
+  }
+  return fd;
+}
+#endif /* !HAVE_ACCEPT4 */
+
 #endif /* !TESTING */
 
 #ifdef TESTING
diff --git a/src/fd_control.h b/src/fd_control.h
index 11d27bf4a04d750b7f26cec1436f5c261702cb80..f1f0d35830bf0166d3f4d0219ba4563a6a5b7c90 100644
--- a/src/fd_control.h
+++ b/src/fd_control.h
@@ -7,6 +7,33 @@
 #ifndef FD_CONTROL_H
 #define FD_CONTROL_H
 
+#ifndef HAVE_ACCEPT4
+/* NB: The default values are compatible with Linux,
+ *     but should work on other OSs as well, since
+ *     accept4(2) is emulated by us anyway.
+ */
+enum pike_sock_flags {
+#ifndef SOCK_CLOEXEC
+#if !defined(SOCK_NONBLOCK) || (SOCK_NONBLOCK != 0x80000)
+  SOCK_CLOEXEC = 0x80000,
+#else
+  /* Unlikely, but... */
+  SOCK_CLOEXEC = 0x40000,
+#endif /* !SOCK_NONBLOCK || SOCK_NONBLOCK != 0x80000 */
+#define SOCK_CLOEXEC	SOCK_CLOEXEC
+#endif
+#ifndef SOCK_NONBLOCK
+#if (SOCK_CLOEXEC != 0x00800)
+  SOCK_NONBLOCK = 0x00800,
+#else
+  /* Unlikely, but... */
+  SOCK_NONBLOCK = 0x00400,
+#endif
+#define SOCK_NONBLOCK	SOCK_NONBLOCK
+#endif
+};
+#endif /* !HAVE_ACCEPT4 */
+
 /* Prototypes begin here */
 PMOD_EXPORT int set_nonblocking(int fd,int which);
 PMOD_EXPORT int query_nonblocking(int fd);
@@ -16,6 +43,9 @@ PMOD_EXPORT int set_close_on_exec(int fd, int which);
 void do_close_on_exec(void);
 void cleanup_close_on_exec(void);
 #endif /* HAVE_BROKEN_F_SETFD */
+#ifndef HAVE_ACCEPT4
+int accept4(int fd, struct sockaddr *addr, ACCEPT_SIZE_T *addrlen, int flags)
+#endif /* !HAVE_ACCEPT4 */
 /* Prototypes end here */
 
 #endif
diff --git a/src/fdlib.h b/src/fdlib.h
index 3b653652b10b706b40c61b0718b60e05e8b0ae99..d3775fffa5fbed1e803ff96fffffb80c3708e613 100644
--- a/src/fdlib.h
+++ b/src/fdlib.h
@@ -90,6 +90,7 @@ typedef off_t PIKE_OFF_T;
 #define fd_socket(X,Y,Z) dmalloc_register_fd(debug_fd_socket((X),(Y),(Z)))
 #define fd_pipe(X) debug_fd_pipe( (X) DMALLOC_POS )
 #define fd_accept(X,Y,Z) dmalloc_register_fd(debug_fd_accept((X),(Y),(Z)))
+#define fd_accept4(X,Y,Z,F) dmalloc_register_fd(accept4((X),(Y),(Z),(F)))
 
 #define fd_bind(fd,X,Y) debug_fd_bind(dmalloc_touch_fd(fd), (X), (Y))
 #define fd_getsockopt(fd,X,Y,Z,Q) debug_fd_getsockopt(dmalloc_touch_fd(fd), (X),(Y),(Z),(Q))
@@ -340,6 +341,7 @@ typedef off_t PIKE_OFF_T;
 #define fd_socket(X,Y,Z) dmalloc_register_fd(socket((X),(Y),(Z)))
 #define fd_pipe pipe /* FIXME */
 #define fd_accept(X,Y,Z) dmalloc_register_fd(accept((X),(Y),(Z)))
+#define fd_accept4(X,Y,Z,F) dmalloc_register_fd(accept4((X),(Y),(Z),(F)))
 
 #define fd_bind(fd,X,Y) bind(dmalloc_touch_fd(fd), (X), (Y))
 #define fd_getsockopt(fd,X,Y,Z,Q) getsockopt(dmalloc_touch_fd(fd), (X),(Y),(Z),(Q))