diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat
index c20fae152..4e2359c64 100644
--- a/doc/sudo_plugin.cat
+++ b/doc/sudo_plugin.cat
@@ -1111,6 +1111,7 @@ DDEESSCCRRIIPPTTIIOONN
      ++oo   SIGALRM
      ++oo   SIGHUP
      ++oo   SIGINT
+     ++oo   SIGPIPE
      ++oo   SIGQUIT
      ++oo   SIGTERM
      ++oo   SIGTSTP
@@ -1121,7 +1122,8 @@ DDEESSCCRRIIPPTTIIOONN
      call the plugin's cclloossee() function with an exit status of 128 plus the
      value of the signal that was received.  This allows for consistent
      logging of commands killed by a signal for plugins that log such
-     information in their cclloossee() function.
+     information in their cclloossee() function.  An exception to this is SIGPIPE,
+     which is ignored until the command is executed.
 
      A plugin may temporarily install its own signal handlers but must restore
      the original handler before the plugin function returns.
diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in
index 67e5c16da..1c47fec55 100644
--- a/doc/sudo_plugin.man.in
+++ b/doc/sudo_plugin.man.in
@@ -1978,6 +1978,9 @@ executed:
 \fRSIGINT\fR
 .TP 4n
 \fB\(bu\fR
+\fRSIGPIPE\fR
+.TP 4n
+\fB\(bu\fR
 \fRSIGQUIT\fR
 .TP 4n
 \fB\(bu\fR
@@ -2003,6 +2006,9 @@ This allows for consistent logging of commands killed by a signal
 for plugins that log such information in their
 \fBclose\fR()
 function.
+An exception to this is
+\fRSIGPIPE\fR,
+which is ignored until the command is executed.
 .PP
 A plugin may temporarily install its own signal handlers but must
 restore the original handler before the plugin function returns.
diff --git a/doc/sudo_plugin.mdoc.in b/doc/sudo_plugin.mdoc.in
index 87c933324..d5507ba73 100644
--- a/doc/sudo_plugin.mdoc.in
+++ b/doc/sudo_plugin.mdoc.in
@@ -1735,6 +1735,8 @@ executed:
 .It
 .Dv SIGINT
 .It
+.Dv SIGPIPE
+.It
 .Dv SIGQUIT
 .It
 .Dv SIGTERM
@@ -1756,6 +1758,9 @@ This allows for consistent logging of commands killed by a signal
 for plugins that log such information in their
 .Fn close
 function.
+An exception to this is
+.Ev SIGPIPE ,
+which is ignored until the command is executed.
 .Pp
 A plugin may temporarily install its own signal handlers but must
 restore the original handler before the plugin function returns.
diff --git a/plugins/sudoers/ldap.c b/plugins/sudoers/ldap.c
index 97c2c756f..00fcb2105 100644
--- a/plugins/sudoers/ldap.c
+++ b/plugins/sudoers/ldap.c
@@ -2975,17 +2975,10 @@ sudo_ldap_open(struct sudo_nss *nss)
 {
     LDAP *ld;
     int rc = -1;
-    sigaction_t sa, saved_sa_pipe;
     bool ldapnoinit = false;
     struct sudo_ldap_handle *handle;
     debug_decl(sudo_ldap_open, SUDOERS_DEBUG_LDAP)
 
-    /* Ignore SIGPIPE if we cannot bind to the server. */
-    memset(&sa, 0, sizeof(sa));
-    sigemptyset(&sa.sa_mask);
-    sa.sa_handler = SIG_IGN;
-    (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
-
     if (!sudo_ldap_read_config())
 	goto done;
 
@@ -3071,7 +3064,6 @@ sudo_ldap_open(struct sudo_nss *nss)
     nss->handle = handle;
 
 done:
-    (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
     debug_return_int(rc == LDAP_SUCCESS ? 0 : -1);
 }
 
diff --git a/plugins/sudoers/logging.c b/plugins/sudoers/logging.c
index cbb18ce00..ed3c8be1e 100644
--- a/plugins/sudoers/logging.c
+++ b/plugins/sudoers/logging.c
@@ -542,7 +542,6 @@ send_mail(const char *fmt, ...)
     const char *timestr;
     int fd, pfd[2], status;
     pid_t pid, rv;
-    sigaction_t sa;
     struct stat sb;
     va_list ap;
 #ifndef NO_ROOT_MAILER
@@ -619,13 +618,6 @@ send_mail(const char *fmt, ...)
     sudo_endgrent();
     closefrom(STDERR_FILENO + 1);
 
-    /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */
-    memset(&sa, 0, sizeof(sa));
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_INTERRUPT;
-    sa.sa_handler = SIG_IGN;
-    (void) sigaction(SIGPIPE, &sa, NULL);
-
     if (pipe(pfd) == -1) {
 	mysyslog(LOG_ERR, _("unable to open pipe: %m"));
 	sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to open pipe: %s",
diff --git a/src/signal.c b/src/signal.c
index 888492fad..28a3b6e3f 100644
--- a/src/signal.c
+++ b/src/signal.c
@@ -30,6 +30,7 @@
 #include <signal.h>
 
 #include "sudo.h"
+#include "sudo_exec.h"
 
 int signal_pipe[2];
 
@@ -151,6 +152,13 @@ init_signals(void)
 		break;
 	}
     }
+    /* Ignore SIGPIPE until exec. */
+    if (saved_signals[SAVED_SIGPIPE].sa.sa_handler != SIG_IGN) {
+	sa.sa_handler = SIG_IGN;
+	if (sigaction(SIGPIPE, &sa, NULL) != 0)
+	    sudo_warn(U_("unable to set handler for signal %d"), SIGPIPE);
+    }
+
     debug_return;
 }
 
diff --git a/src/sudo.c b/src/sudo.c
index d4be82acd..46e5ce44f 100644
--- a/src/sudo.c
+++ b/src/sudo.c
@@ -188,10 +188,13 @@ main(int argc, char *argv[], char *envp[])
     /* Make sure we are setuid root. */
     sudo_check_suid(argc > 0 ? argv[0] : "sudo");
 
-    /* Reset signal mask and save signal state. */
+    /* Save original signal state and setup default signal handlers. */
+    save_signals();
+    init_signals();
+
+    /* Reset signal mask to the default value (unblock). */
     (void) sigemptyset(&mask);
     (void) sigprocmask(SIG_SETMASK, &mask, NULL);
-    save_signals();
 
     /* Parse the rest of sudo.conf. */
     sudo_conf_read(NULL, SUDO_CONF_ALL & ~SUDO_CONF_DEBUG);
@@ -230,8 +233,6 @@ main(int argc, char *argv[], char *envp[])
 	    sudo_fatalx(U_("unable to initialize policy plugin"));
     }
 
-    init_signals();
-
     switch (sudo_mode & MODE_MASK) {
 	case MODE_VERSION:
 	    policy_show_version(&policy_plugin, !user_details.uid);
diff --git a/src/tgetpass.c b/src/tgetpass.c
index 47291bc1f..671c021d8 100644
--- a/src/tgetpass.c
+++ b/src/tgetpass.c
@@ -85,7 +85,7 @@ tgetpass(const char *prompt, int timeout, int flags,
     struct sudo_conv_callback *callback)
 {
     sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm;
-    sigaction_t savetstp, savettin, savettou, savepipe;
+    sigaction_t savetstp, savettin, savettou;
     char *pass;
     static const char *askpass;
     static char buf[SUDO_CONV_REPL_MAX + 1];
@@ -168,10 +168,6 @@ restart:
     (void) sigaction(SIGTTIN, &sa, &savettin);
     (void) sigaction(SIGTTOU, &sa, &savettou);
 
-    /* Ignore SIGPIPE in case stdin is a pipe and TGP_STDIN is set */
-    sa.sa_handler = SIG_IGN;
-    (void) sigaction(SIGPIPE, &sa, &savepipe);
-
     if (prompt) {
 	if (write(output, prompt, strlen(prompt)) == -1)
 	    goto restore;
@@ -198,7 +194,6 @@ restore:
     (void) sigaction(SIGTSTP, &savetstp, NULL);
     (void) sigaction(SIGTTIN, &savettin, NULL);
     (void) sigaction(SIGTTOU, &savettou, NULL);
-    (void) sigaction(SIGPIPE, &savepipe, NULL);
 
     /* Restore old tty settings. */
     if (!ISSET(flags, TGP_ECHO)) {
@@ -252,7 +247,6 @@ static char *
 sudo_askpass(const char *askpass, const char *prompt)
 {
     static char buf[SUDO_CONV_REPL_MAX + 1], *pass;
-    sigaction_t sa, saved_sa_pipe;
     int pfd[2], status;
     pid_t child;
     debug_decl(sudo_askpass, SUDO_DEBUG_CONV)
@@ -286,18 +280,10 @@ sudo_askpass(const char *askpass, const char *prompt)
 	_exit(255);
     }
 
-    /* Ignore SIGPIPE in case child exits prematurely */
-    memset(&sa, 0, sizeof(sa));
-    sigemptyset(&sa.sa_mask);
-    sa.sa_flags = SA_INTERRUPT;
-    sa.sa_handler = SIG_IGN;
-    (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe);
-
-    /* Get response from child (askpass) and restore SIGPIPE handler */
+    /* Get response from child (askpass). */
     (void) close(pfd[1]);
     pass = getln(pfd[0], buf, sizeof(buf), 0);
     (void) close(pfd[0]);
-    (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL);
 
     /* Wait for child to exit. */
     for (;;) {
