Modified the fcntl system call so that only those reason codes which
can block (ie F_SETLKW) are treated as blocking.

This resolves the F_SETOWN problem described in bug #85969.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2535 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_syscalls.c b/coregrind/vg_syscalls.c
index 2b4f89a..d6f03cf 100644
--- a/coregrind/vg_syscalls.c
+++ b/coregrind/vg_syscalls.c
@@ -2117,6 +2117,8 @@
 {
    /* int fcntl(int fd, int cmd, int arg); */
    MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
+   if (arg2 == VKI_F_SETLKW)
+      tst->sys_flags |= MayBlock;
 }
 
 POST(fcntl)
@@ -2156,6 +2158,8 @@
 {
    /* int fcntl64(int fd, int cmd, int arg); */
    MAYBE_PRINTF("fcntl64 ( %d, %d, %d )\n", arg1,arg2,arg3);
+   if (arg2 == VKI_F_SETLKW || arg2 == VKI_F_SETLKW64)
+      tst->sys_flags |= MayBlock;
 }
 
 POST(fcntl64)
@@ -5644,12 +5648,12 @@
    SYSBA(close,			0),
    SYSBA(dup,			0),
    SYSBA(dup2,			0),
-   SYSBA(fcntl,			MayBlock),
+   SYSBA(fcntl,			0),
    SYSB_(fchdir,		0),
    SYSB_(fchown32,		0),
    SYSB_(fchown,		0),
    SYSB_(fchmod,		0),
-   SYSBA(fcntl64,		MayBlock),
+   SYSBA(fcntl64,		0),
    SYSBA(fstat,			0),
    SYSBA(fork,			0),
    SYSB_(fsync,			MayBlock),
diff --git a/include/vg_kerneliface.h b/include/vg_kerneliface.h
index 6a8c30d..79580fb 100644
--- a/include/vg_kerneliface.h
+++ b/include/vg_kerneliface.h
@@ -546,6 +546,12 @@
 #define VKI_F_SETFD	    2	    /* set/clear close_on_exec */
 #define VKI_F_GETFL         3       /* get file->f_flags */
 #define VKI_F_SETFL         4       /* set file->f_flags */
+#define VKI_F_GETLK         5
+#define VKI_F_SETLK         6
+#define VKI_F_SETLKW        7
+#define VKI_F_GETLK64       12      /*  using 'struct flock64' */
+#define VKI_F_SETLK64       13
+#define VKI_F_SETLKW64      14
 
 /* for F_[GET|SET]FL */
 #define VKI_FD_CLOEXEC	    1	    /* actually anything with low bit set goes */
diff --git a/none/tests/.cvsignore b/none/tests/.cvsignore
index af94caa..ecc0a99 100644
--- a/none/tests/.cvsignore
+++ b/none/tests/.cvsignore
@@ -13,6 +13,7 @@
 discard
 exec-sigmask
 execve
+fcntl_setown
 floored
 fork
 fpu_lazy_eflags
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
index b929d83..6dc2564 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -28,6 +28,7 @@
 	discard.vgtest \
 	exec-sigmask.vgtest exec-sigmask.stdout.exp exec-sigmask.stderr.exp \
 	execve.vgtest execve.stdout.exp execve.stderr.exp \
+	fcntl_setown.vgtest fcntl_setown.stdout.exp fcntl_setown.stderr.exp \
 	floored.stderr.exp floored.stdout.exp \
 	floored.vgtest \
 	fork.stderr.exp fork.stdout.exp fork.vgtest \
@@ -68,7 +69,7 @@
 
 check_PROGRAMS = \
 	args badseg bitfield1 bt_everything bt_literal closeall coolo_strlen \
-	cpuid dastest discard exec-sigmask execve floored fork \
+	cpuid dastest discard exec-sigmask execve fcntl_setown floored fork \
 	fpu_lazy_eflags fucomip $(INSN_TESTS) \
 	int munmap_exe map_unmap mremap rcl_assert rcrl readline1 \
 	resolv rlimit_nofile seg_override sem semlimit sha1_test \
@@ -92,6 +93,7 @@
 discard_SOURCES 	= discard.c
 exec_sigmask_SOURCES	= exec-sigmask.c
 execve_SOURCES		= execve.c
+fcntl_setown_SOURCES	= fcntl_setown.c
 fork_SOURCES 		= fork.c
 floored_SOURCES 	= floored.c
 floored_LDADD 		= -lm
diff --git a/none/tests/fcntl_setown.c b/none/tests/fcntl_setown.c
new file mode 100644
index 0000000..b0ccf64
--- /dev/null
+++ b/none/tests/fcntl_setown.c
@@ -0,0 +1,30 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+   int s;
+  
+   if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0)
+   {
+      perror("socket");
+      exit(1);
+   }
+
+   if (fcntl(s, F_SETOWN, getpid()) < 0)
+   {
+      perror("fcntl(F_SETOWN)");
+      exit(1);
+   }
+   
+   if (close(s) < 0)
+   {
+      perror("close");
+      exit(1);
+   }
+  
+   exit(0);
+}
diff --git a/none/tests/fcntl_setown.stderr.exp b/none/tests/fcntl_setown.stderr.exp
new file mode 100644
index 0000000..139597f
--- /dev/null
+++ b/none/tests/fcntl_setown.stderr.exp
@@ -0,0 +1,2 @@
+
+
diff --git a/none/tests/fcntl_setown.stdout.exp b/none/tests/fcntl_setown.stdout.exp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/none/tests/fcntl_setown.stdout.exp
diff --git a/none/tests/fcntl_setown.vgtest b/none/tests/fcntl_setown.vgtest
new file mode 100644
index 0000000..12adeb8
--- /dev/null
+++ b/none/tests/fcntl_setown.vgtest
@@ -0,0 +1 @@
+prog: fcntl_setown