Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteffen Kieß <s-kiess@web.de>2019-08-30 20:13:33 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2019-08-30 20:13:33 +0300
commit80b7813d54bbf7e3e20361228e109b2b9abcccb5 (patch)
tree9a5b9ae122973b64ffacfac92fbc7429bbfc50cf /mcs/class/Mono.Posix
parentc8707c6e84ed5978fb21be3c2dd4fe678b904c9c (diff)
[Mono.Posix] Add FcntlCommand.F_OFD_{GETLK,SETLK,SETLKW} (#16571)
Add F_OFD_GETLK, F_OFD_SETLK and F_OFD_SETLKW to FcntlCommand. These commmands are similar to F_GETLK, F_SETLK and F_SETLKW but operate on a per-open-file-description lock instead of a per-process lock and avoid the problem that the locks are released when close(dup(fd)) is called. See https://lwn.net/Articles/586904/ for more information. This commit also reruns create-native-map but keeps manual changes from ed892ccf27849c082ce6ca46fa8b96d86ca7c329, b522eab5ff5466debaacf9e971e26cfc464ebba5 and 22b6b9581418260397b701c17b16c3eb55136de7. In [create-native-map.diff.txt](https://github.com/mono/mono/files/3557077/create-native-map.diff.txt) you can see the difference between the commited `map.[ch]` and the one `create-native-map.exe` wants to create: - Manually inserted changes for NetBSD (`MAYMOVE` is turned into a negated `FIXED`) - `Mono_Posix_ToSockaddrIn6()` and friends get skipped for `HOST_WIN32` (not sure why, when `sockaddr_in6` exists then `Mono_Posix_ToSockaddrIn6()` should work) - At the bottom of `map.h` some functions are reordered and the parameters change (`const char*` vs. `char*`) Running create-native-map.exe also moved some O_NOATIME-related stuff (from 8b9033e4d24115190c06f775d18ef3a40cbca876) to the correct position and added it to Mono_Posix_ToOpenFlags(), which I kept in the commit.
Diffstat (limited to 'mcs/class/Mono.Posix')
-rw-r--r--mcs/class/Mono.Posix/Mono.Posix_test.dll.sources1
-rw-r--r--mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs35
-rw-r--r--mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs133
3 files changed, 153 insertions, 16 deletions
diff --git a/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources b/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
index a2f290f8656..5aee212abe7 100644
--- a/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
+++ b/mcs/class/Mono.Posix/Mono.Posix_test.dll.sources
@@ -9,6 +9,7 @@ Mono.Unix/UnixPathTest.cs
Mono.Unix/UnixSignalTest.cs
Mono.Unix/UnixUserTest.cs
Mono.Unix.Android/TestHelper.cs
+Mono.Unix.Native/OFDLockTest.cs
Mono.Unix.Native/RealTimeSignumTests.cs
Mono.Unix.Native/SocketTest.cs
Mono.Unix.Native/StdlibTest.cs
diff --git a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
index 6cc67dda4b8..c9eb750d222 100644
--- a/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
+++ b/mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
@@ -212,22 +212,25 @@ namespace Mono.Unix.Native {
[CLSCompliant (false)]
public enum FcntlCommand : int {
// Form /usr/include/bits/fcntl.h
- F_DUPFD = 0, // Duplicate file descriptor.
- F_GETFD = 1, // Get file descriptor flags.
- F_SETFD = 2, // Set file descriptor flags.
- F_GETFL = 3, // Get file status flags.
- F_SETFL = 4, // Set file status flags.
- F_GETLK = 12, // Get record locking info. [64]
- F_SETLK = 13, // Set record locking info (non-blocking). [64]
- F_SETLKW = 14, // Set record locking info (blocking). [64]
- F_SETOWN = 8, // Set owner of socket (receiver of SIGIO).
- F_GETOWN = 9, // Get owner of socket (receiver of SIGIO).
- F_SETSIG = 10, // Set number of signal to be sent.
- F_GETSIG = 11, // Get number of signal to be sent.
- F_NOCACHE = 48, // OSX: turn data caching off/on for this fd.
- F_SETLEASE = 1024, // Set a lease.
- F_GETLEASE = 1025, // Enquire what lease is active.
- F_NOTIFY = 1026, // Required notifications on a directory
+ F_DUPFD = 0, // Duplicate file descriptor.
+ F_GETFD = 1, // Get file descriptor flags.
+ F_SETFD = 2, // Set file descriptor flags.
+ F_GETFL = 3, // Get file status flags.
+ F_SETFL = 4, // Set file status flags.
+ F_GETLK = 12, // Get record locking info. [64]
+ F_SETLK = 13, // Set record locking info (non-blocking). [64]
+ F_SETLKW = 14, // Set record locking info (blocking). [64]
+ F_OFD_GETLK = 36, // Get open file description locking info.
+ F_OFD_SETLK = 37, // Set open file description locking info (non-blocking).
+ F_OFD_SETLKW = 38, // Set open file description locking info (blocking).
+ F_SETOWN = 8, // Set owner of socket (receiver of SIGIO).
+ F_GETOWN = 9, // Get owner of socket (receiver of SIGIO).
+ F_SETSIG = 10, // Set number of signal to be sent.
+ F_GETSIG = 11, // Get number of signal to be sent.
+ F_NOCACHE = 48, // OSX: turn data caching off/on for this fd.
+ F_SETLEASE = 1024, // Set a lease.
+ F_GETLEASE = 1025, // Enquire what lease is active.
+ F_NOTIFY = 1026, // Required notifications on a directory
}
[Map]
diff --git a/mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs b/mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs
new file mode 100644
index 00000000000..44f45fe0187
--- /dev/null
+++ b/mcs/class/Mono.Posix/Test/Mono.Unix.Native/OFDLockTest.cs
@@ -0,0 +1,133 @@
+//
+// Tests for FcntlCommand.F_OFD_{GETLK,SETLK,SETLKW}
+//
+// Authors:
+// Steffen Kiess (kiess@ki4.de)
+//
+// Copyright (C) 2019 Steffen Kiess
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+
+using Mono.Unix;
+using Mono.Unix.Native;
+
+using NUnit.Framework;
+
+namespace MonoTests.Mono.Unix.Native
+{
+ [TestFixture, Category ("NotDotNet"), Category ("NotOnWindows"), Category ("NotOnMac")]
+ public class OFDLockTest {
+
+ string TempFolder;
+
+ [SetUp]
+ public void SetUp ()
+ {
+ TempFolder = Path.Combine (Path.GetTempPath (), this.GetType ().FullName);
+
+ if (Directory.Exists (TempFolder))
+ Directory.Delete (TempFolder, true);
+
+ Directory.CreateDirectory (TempFolder);
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ if (Directory.Exists (TempFolder))
+ Directory.Delete (TempFolder, true);
+ }
+
+ [Test]
+ public void TestOFDLock ()
+ {
+ int fd1 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR | OpenFlags.O_CREAT | OpenFlags.O_EXCL, FilePermissions.DEFFILEMODE);
+ if (fd1 < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ int fd2 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR);
+ if (fd2 < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ int fd3 = Syscall.open (TempFolder + "/testfile", OpenFlags.O_RDWR);
+ if (fd3 < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Get read lock for first 100 bytes on fd1
+ var flock1 = new Flock {
+ l_type = LockType.F_RDLCK,
+ l_whence = SeekFlags.SEEK_SET,
+ l_start = 0,
+ l_len = 100,
+ };
+ if (Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLKW, ref flock1) < 0) {
+ // Old kernels and non-linux systems should return EINVAL
+ if (Stdlib.GetLastError () == Errno.EINVAL)
+ Assert.Ignore ("F_OFD_SETLKW does not seem to be supported.");
+ UnixMarshal.ThrowExceptionForLastError ();
+ }
+
+ // Get read lock for first 100 bytes on fd2
+ var flock2 = new Flock {
+ l_type = LockType.F_RDLCK,
+ l_whence = SeekFlags.SEEK_SET,
+ l_start = 0,
+ l_len = 100,
+ };
+ if (Syscall.fcntl (fd2, FcntlCommand.F_OFD_SETLK, ref flock2) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Get write lock for remaining bytes on fd1
+ var flock3 = new Flock {
+ l_type = LockType.F_WRLCK,
+ l_whence = SeekFlags.SEEK_SET,
+ l_start = 100,
+ l_len = 0,
+ };
+ if (Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLK, ref flock3) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Close fd3, should not release lock
+ if (Syscall.close (fd3) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+
+ // Get lock status for byte 150 from fd2
+ var flock4 = new Flock {
+ l_type = LockType.F_RDLCK,
+ l_whence = SeekFlags.SEEK_SET,
+ l_start = 150,
+ l_len = 1,
+ };
+ if (Syscall.fcntl (fd2, FcntlCommand.F_OFD_GETLK, ref flock4) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ // There should be a conflicting write lock
+ Assert.AreEqual (LockType.F_WRLCK, flock4.l_type);
+
+ // Get write byte 0 on fd1, should fail with EAGAIN
+ var flock5 = new Flock {
+ l_type = LockType.F_WRLCK,
+ l_whence = SeekFlags.SEEK_SET,
+ l_start = 0,
+ l_len = 1,
+ };
+ var res = Syscall.fcntl (fd1, FcntlCommand.F_OFD_SETLK, ref flock5);
+ Assert.AreEqual (-1, res);
+ Assert.AreEqual (Errno.EAGAIN, Stdlib.GetLastError ());
+
+ if (Syscall.close (fd1) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ if (Syscall.close (fd2) < 0)
+ UnixMarshal.ThrowExceptionForLastError ();
+ }
+ }
+}
+
+// vim: noexpandtab
+// Local Variables:
+// tab-width: 4
+// c-basic-offset: 4
+// indent-tabs-mode: t
+// End: