Skip to content

Commit 9d6fa23

Browse files
authored
Implement file locking in SQLite on Posix (#1938)
1 parent 765abf2 commit 9d6fa23

File tree

2 files changed

+72
-23
lines changed

2 files changed

+72
-23
lines changed

src/extensions/IronPython.SQLite/IronPython.SQLite.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@
2323
<DefineConstants>NET_40;$(DefineConstants);$(SQLiteCommon);$(SQLiteCommonOmit);SQLITE_MUTEX_W32;SQLITE_THREADSAFE;NDEBUG</DefineConstants>
2424
</PropertyGroup>
2525

26+
<ItemGroup Condition=" '$(IsFullFramework)' == 'true' ">
27+
<Reference Include="Mono.Posix" Version="4.0.0">
28+
<Private>True</Private>
29+
<HintPath>$(UtilsDir)\References\Mono.Posix.dll</HintPath>
30+
</Reference>
31+
</ItemGroup>
32+
<ItemGroup Condition=" '$(IsFullFramework)' != 'true' ">
33+
<PackageReference Include="Mono.Unix" Version="7.1.0-final.1.21458.1" />
34+
</ItemGroup>
35+
36+
<ItemGroup>
37+
<Compile Include="../../core/IronPython/FakeInteropServices.cs" />
38+
</ItemGroup>
39+
2640
<ItemGroup>
2741
<ProjectReference Include="..\..\core\IronPython\IronPython.csproj" Private="false" />
2842
<ProjectReference Include="..\..\dlr\Src\Microsoft.Scripting\Microsoft.Scripting.csproj" Private="false" />

src/extensions/IronPython.SQLite/c#sqlite/os_win_c.cs

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
#elif WINDOWS_PHONE || SQLITE_SILVERLIGHT
2222
using System.IO.IsolatedStorage;
2323
#endif
24+
#if !FEATURE_RUNTIMEINFORMATION
25+
using IronPython;
26+
#endif
2427
namespace Community.CsharpSqlite
2528
{
2629
public partial class Sqlite3
@@ -3713,27 +3716,53 @@ static extern bool LockFileEx( IntPtr hFile, uint dwFlags, uint dwReserved,
37133716

37143717
const int LOCKFILE_FAIL_IMMEDIATELY = 1;
37153718
#endif
3716-
public virtual void LockFile( sqlite3_file pFile, long offset, long length )
3719+
3720+
private int LockUnix( sqlite3_file pFile, long offset, long length, bool locking, bool shared = false)
3721+
{
3722+
int fd = pFile.fs.Handle.ToInt32();
3723+
Mono.Unix.Native.Flock flock = new() {
3724+
l_whence = Mono.Unix.Native.SeekFlags.SEEK_SET,
3725+
l_start = offset,
3726+
l_len = length,
3727+
l_type = !locking ? Mono.Unix.Native.LockType.F_UNLCK
3728+
: shared ? Mono.Unix.Native.LockType.F_RDLCK
3729+
: Mono.Unix.Native.LockType.F_WRLCK,
3730+
};
3731+
3732+
int result = Mono.Unix.Native.Syscall.fcntl(fd, Mono.Unix.Native.FcntlCommand.F_SETLK, ref flock);
3733+
return result != -1 ? 1 : 0;
3734+
}
3735+
3736+
public virtual void LockFile( sqlite3_file pFile, long offset, long length )
3737+
{
3738+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
37173739
{
3718-
#pragma warning disable CA1416 // Validate platform compatibility
3719-
pFile.fs.Lock( offset, length );
3720-
#pragma warning restore CA1416 // Validate platform compatibility
3740+
LockUnix( pFile, offset, length, locking: true );
37213741
}
3742+
else
3743+
{
3744+
pFile.fs.Lock( offset, length );
3745+
}
3746+
}
37223747

37233748
public virtual int SharedLockFile( sqlite3_file pFile, long offset, long length )
3724-
{
3749+
{
37253750
#if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE || SQLITE_WINRT)
3726-
#if FEATURE_RUNTIMEINFORMATION
3727-
Debug.Assert(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));
3728-
#endif
3729-
Debug.Assert( length == SHARED_SIZE );
3730-
Debug.Assert( offset == SHARED_FIRST );
3731-
NativeOverlapped ovlp = new NativeOverlapped();
3732-
ovlp.OffsetLow = (int)offset;
3733-
ovlp.OffsetHigh = 0;
3734-
ovlp.EventHandle = IntPtr.Zero;
3735-
3736-
return LockFileEx( pFile.fs.Handle, LOCKFILE_FAIL_IMMEDIATELY, 0, (uint)length, 0, ref ovlp ) ? 1 : 0;
3751+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
3752+
{
3753+
Debug.Assert( length == SHARED_SIZE );
3754+
Debug.Assert( offset == SHARED_FIRST );
3755+
NativeOverlapped ovlp = new NativeOverlapped();
3756+
ovlp.OffsetLow = (int)offset;
3757+
ovlp.OffsetHigh = 0;
3758+
ovlp.EventHandle = IntPtr.Zero;
3759+
3760+
return LockFileEx( pFile.fs.Handle, LOCKFILE_FAIL_IMMEDIATELY, 0, (uint)length, 0, ref ovlp ) ? 1 : 0;
3761+
}
3762+
else
3763+
{
3764+
return LockUnix( pFile, offset, length, locking: true, shared: true );
3765+
}
37373766
#else
37383767
return 1;
37393768
#endif
@@ -3742,9 +3771,14 @@ public virtual int SharedLockFile( sqlite3_file pFile, long offset, long length
37423771
public virtual void UnlockFile( sqlite3_file pFile, long offset, long length )
37433772
{
37443773
#if !(SQLITE_SILVERLIGHT || WINDOWS_MOBILE || SQLITE_WINRT)
3745-
#pragma warning disable CA1416 // Validate platform compatibility
3746-
pFile.fs.Unlock( offset, length );
3747-
#pragma warning restore CA1416 // Validate platform compatibility
3774+
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
3775+
{
3776+
LockUnix( pFile, offset, length, locking: false );
3777+
}
3778+
else
3779+
{
3780+
pFile.fs.Unlock( offset, length );
3781+
}
37483782
#endif
37493783
}
37503784
}
@@ -3762,9 +3796,10 @@ public override int SharedLockFile( sqlite3_file pFile, long offset, long length
37623796
Debug.Assert( offset == SHARED_FIRST );
37633797
try
37643798
{
3765-
#pragma warning disable CA1416 // Validate platform compatibility
3766-
pFile.fs.Lock( offset + pFile.sharedLockByte, 1 );
3767-
#pragma warning restore CA1416 // Validate platform compatibility
3799+
if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
3800+
{
3801+
pFile.fs.Lock( offset + pFile.sharedLockByte, 1 );
3802+
}
37683803
}
37693804
catch ( IOException )
37703805
{
@@ -3781,7 +3816,7 @@ public static bool IsRunningMediumTrust() {
37813816
// placeholder method
37823817
// this is where it needs to check if it's running in an ASP.Net MediumTrust or lower environment
37833818
// in order to pick the appropriate locking strategy
3784-
return Environment.OSVersion.Platform == PlatformID.Unix;
3819+
return false;
37853820
}
37863821

37873822
#if SQLITE_WINRT

0 commit comments

Comments
 (0)