-
Couldn't load subscription status.
- Fork 83
Description
nuget 2.0 .netstandard
Hi, I’ve been investigating some intermittent LightningException errors when opening environments, and traced the root cause to the way mdb_env_open is called from managed code.
In the current implementation:
[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
public static extern MDBResultCode mdb_env_open(
[NativeInteger] IntPtr env,
byte[] path,
EnvironmentOpenFlags flags,
UnixAccessMode mode);
internal static MDBResultCode mdb_env_open(
[NativeInteger] IntPtr env,
string path,
EnvironmentOpenFlags flags,
UnixAccessMode mode)
{
byte[] bytes = Encoding.UTF8.GetBytes(path);
return Lmdb.mdb_env_open(env, bytes, flags, mode);
}
The managed wrapper converts the string path to a UTF-8 byte[], but does not append a null terminator.
LMDB expects a const char* that is zero-terminated. Without the trailing \0, the native side reads past the end of the buffer, causing random memory reads and file names like data.mdbo to appear in Process Monitor. This also explains why the error was non-deterministic — it depended on whatever byte happened to follow the managed array in memory.
Fix
Either:
Add a null terminator manually when building the byte array:
byte[] bytes = Encoding.UTF8.GetBytes(path + "\0");
or
Change the P/Invoke to use proper string marshaling:
[DllImport("lmdb", CallingConvention = CallingConvention.Cdecl)]
private static extern MDBResultCode mdb_env_open(
IntPtr env,
[MarshalAs(UnmanagedType.LPUTF8Str)] string path,
EnvironmentOpenFlags flags,
UnixAccessMode mode);