Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2101

kernel-2.6.18-238.el5.src.rpm

From: Jiri Pirko <jpirko@redhat.com>
Date: Thu, 26 Jun 2008 19:50:04 +0200
Subject:  [misc] signaling msgrvc() should not pass back error
Message-id: 4863D6CC.8080402@redhat.com
O-Subject: [RHEL5.2 patch] BZ452533 The msgrcv() syscall fails with error number 514 (ERESTARTNOHAND)
Bugzilla: 452533
RH-Acked-by: Pete Zaitcev <zaitcev@redhat.com>
RH-Acked-by: Roland McGrath <roland@redhat.com>

BZ452533
https://bugzilla.redhat.com/show_bug.cgi?id=452533

Description
When the user program gets a signal while calling the msgrcv(),
msgrcv() returns with error number that indicates the program got a
signal. However, msgrcv() returns with a wrong error number
514(ERESTARTNOHAND), frequently. This error number is only used inner
kernel and should never be seen by user programs

Upstream status:
b74d0deb968e1f85942f17080eace015ce3c332c

Brew build:
http://brewweb.devel.redhat.com/brew/taskinfo?taskID=1367595

Test status:
Booted on x86_64 and tested by reproducer program attached in Issue Tracker. Mentioned issue did not happen with patched kernel.

Jirka

 kernel/signal.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 201917b..53fb8cf 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -100,7 +100,11 @@ static int recalc_sigpending_tsk(struct task_struct *t)
 		set_tsk_thread_flag(t, TIF_SIGPENDING);
 		return 1;
 	}
-	clear_tsk_thread_flag(t, TIF_SIGPENDING);
+	/*
+	 * We must never clear the flag in another thread, or in current
+	 * when it's possible the current syscall is returning -ERESTART*.
+	 * So we don't clear it here, and only callers who know they should do.
+	 */
 	return 0;
 }
 
@@ -116,7 +120,9 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-	recalc_sigpending_tsk(current);
+	if (!recalc_sigpending_tsk(current))
+		clear_thread_flag(TIF_SIGPENDING);
+
 }
 
 /* Given the mask, find the first available signal that should be serviced. */
@@ -327,7 +333,6 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
 			sig = 0;
 				
 	}
-	recalc_sigpending();
 
 	return sig;
 }
@@ -344,7 +349,8 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 	if (!signr)
 		signr = __dequeue_signal(&tsk->signal->shared_pending,
 					 mask, info);
- 	if (signr && unlikely(sig_kernel_stop(signr))) {
+	recalc_sigpending();
+	if (signr && unlikely(sig_kernel_stop(signr))) {
  		/*
  		 * Set a marker that we have dequeued a stop signal.  Our
  		 * caller might release the siglock and then the pending