diff --git a/nptl/Versions b/nptl/Versions
index f7140277f5..17a711dfb1 100644
--- a/nptl/Versions
+++ b/nptl/Versions
@@ -285,5 +285,6 @@ libpthread {
     __pthread_barrier_init; __pthread_barrier_wait;
     __shm_directory;
     __libpthread_freeres;
+    __pthread_create_internal;
   }
 }
diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h
index c4e72f57a9..4e065ace58 100644
--- a/nptl/pthreadP.h
+++ b/nptl/pthreadP.h
@@ -339,6 +339,16 @@ extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe);
 hidden_proto (__pthread_cleanup_upto)
 #endif
 
+/* Exactly like pthread_create if NEW_SIGMASK == NULL.  Otherwise, do
+   not use the current signal mask for the new thread, but set it to
+   *NEW_SIGMASK instead (without unblocking internal signals).  */
+extern int __pthread_create_internal (pthread_t *newthread,
+				      const pthread_attr_t *attr,
+				      void *(*start_routine) (void *),
+				      void *arg, const sigset_t *new_sigmask);
+#if IS_IN (libpthread)
+hidden_proto (__pthread_create_internal)
+#endif
 
 /* Functions with versioned interfaces.  */
 extern int __pthread_create_2_1 (pthread_t *newthread,
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index afd379e89a..2430d65723 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -603,10 +603,10 @@ report_thread_creation (struct pthread *pd)
   return false;
 }
 
-
 int
-__pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
-		      void *(*start_routine) (void *), void *arg)
+__pthread_create_internal (pthread_t *newthread, const pthread_attr_t *attr,
+			   void *(*start_routine) (void *), void *arg,
+			   const sigset_t *new_sigmask)
 {
   STACK_VARIABLES;
 
@@ -762,14 +762,21 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
   sigset_t original_sigmask;
   __libc_signal_block_all (&original_sigmask);
 
-  /* Conceptually, the new thread needs to inherit the signal mask of
-     this thread.  Therefore, it needs to restore the saved signal
-     mask of this thread, so save it in the startup information.  */
-  pd->sigmask = original_sigmask;
+  if (new_sigmask != NULL)
+    /* The caller supplied the signal mask for the new thread.  */
+    pd->sigmask = *new_sigmask;
+  else
+    {
+      /* Conceptually, the new thread needs to inherit the signal mask
+	 of this thread.  Therefore, it needs to restore the saved
+	 signal mask of this thread, so save it in the startup
+	 information.  */
+      pd->sigmask = original_sigmask;
 
-  /* Reset the cancellation signal mask in case this thread is running
-     cancellation.  */
-  __sigdelset (&pd->sigmask, SIGCANCEL);
+      /* Reset the cancellation signal mask in case this thread is
+	 running cancellation.  */
+      __sigdelset (&pd->sigmask, SIGCANCEL);
+    }
 
   /* Start the thread.  */
   if (__glibc_unlikely (report_thread_creation (pd)))
@@ -873,6 +880,15 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
 
   return retval;
 }
+hidden_def (__pthread_create_internal)
+
+int
+__pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
+		      void *(*start_routine) (void *), void *arg)
+{
+  return __pthread_create_internal (newthread, attr, start_routine, arg,
+				    false);
+}
 versioned_symbol (libpthread, __pthread_create_2_1, pthread_create, GLIBC_2_1);
 
 
diff --git a/sysdeps/unix/sysv/linux/timer_routines.c b/sysdeps/unix/sysv/linux/timer_routines.c
index 63083f6f91..7a5fa3dbb2 100644
--- a/sysdeps/unix/sysv/linux/timer_routines.c
+++ b/sysdeps/unix/sysv/linux/timer_routines.c
@@ -136,23 +136,19 @@ __start_helper_thread (void)
   (void) pthread_attr_init (&attr);
   (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr));
 
-  /* Block all signals in the helper thread but SIGSETXID.  To do this
-     thoroughly we temporarily have to block all signals here.  The
-     helper can lose wakeups if SIGTIMER is not blocked throughout.  */
-  sigset_t ss;
-  __libc_signal_block_app (&ss);
-  __libc_signal_block_sigtimer (NULL);
+  /* Block all signals in the helper thread but SIGSETXID.  */
+  sigset_t new_sigmask;
+  __sigfillset (&new_sigmask);
+  __sigdelset (&new_sigmask, SIGSETXID);
 
   /* Create the helper thread for this timer.  */
   pthread_t th;
-  int res = pthread_create (&th, &attr, timer_helper_thread, NULL);
+  int res = __pthread_create_internal (&th, &attr, timer_helper_thread, NULL,
+				       &new_sigmask);
   if (res == 0)
     /* We managed to start the helper thread.  */
     __helper_tid = ((struct pthread *) th)->tid;
 
-  /* Restore the signal mask.  */
-  __libc_signal_restore_set (&ss);
-
   /* No need for the attribute anymore.  */
   (void) pthread_attr_destroy (&attr);
 
