I snipped this out of the other topic, since this is quite likely another problem.
Here goes:
There seems to be something strange with the self encryptor callbacks and so on…
I’m referencing the C#
method names, but they are more or less the same as the underlying api method names.
It appeared like IDataSelfEncryptorWriterFree
was not needed when calling IDataCloseSelfEncryptor
The pattern for reader however is different. There is no example of using CloseSelfEncryptorAsync
for the reader, and so there we actually need to call IDataSelfEncryptorReaderFree
, otherwise there would be a memory leak, and eventually the machine would run out of memory.
But, it seems like this sequence of calls:
async Task<EventData> GetEventDataFromAddress(StoredEvent stored)
{
var seReaderHandle = await IData.FetchSelfEncryptorAsync(stored.DataMapAddress);
var len = await IData.SizeAsync(seReaderHandle);
var readData = await IData.ReadFromSelfEncryptorAsync(seReaderHandle, 0, len);
var eventData = new EventData(readData.ToArray(),
stored.MetaData.CorrelationId,
stored.MetaData.CausationId,
stored.MetaData.EventClrType,
stored.MetaData.Id,
stored.MetaData.Name,
stored.MetaData.SequenceNumber,
stored.MetaData.TimeStamp);
await IData.SelfEncryptorReaderFreeAsync(seReaderHandle);
return eventData;
}
leads to some strange things:
In the image above, an IDataSizeCb
is clearly returned from native code, when expecting an IDataSelfEncryptorReaderFreeCb
. Then on another occasion, it is a IDataFetchSelfEncryptorCb
returned from native code.
Same method call, same parameter types, but returning pointers to different kind of callbacks?
I have no idea how this happens, but there is without doubt something wrong.
So, the code that is called is identical to SafeMessages example
:
public void IDataSelfEncryptorReaderFree(IntPtr appPtr, ulong sEReaderHandle,
IDataSelfEncryptorReaderFreeCb callback)
{
IDataSelfEncryptorReaderFreeNative(appPtr, sEReaderHandle, callback.ToHandlePtr(),
OnIDataSelfEncryptorReaderFreeCb);
}
[DllImport("safe_app.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "idata_self_encryptor_reader_free")]
public static extern void IDataSelfEncryptorReaderFreeNative(
IntPtr appPtr,
ulong sEReaderHandle,
IntPtr self,
IDataSelfEncryptorReaderFreeCb callback);
private static void OnIDataSelfEncryptorReaderFreeCb(IntPtr self, FfiResult result)
{
var cb = self.HandlePtrToType<IDataSelfEncryptorReaderFreeCb>();
cb(IntPtr.Zero, result);
}
So you can see that when calling the idata_self_encryptor_reader_free
we are expecting one kind of callback, but getting a few various kinds of callbacks returned from native code. This is quite weird.
Something seems to be messing this up, making things go haywire. Is there something wrong with how I call the read and write of immutable data, that is messing up the native state?
For reference, here is how I write immutable data:
async Task<List<byte>> StoreImmutableData(byte[] payload)
{
var cipherOptHandle = await CipherOpt.NewPlaintextAsync();
var seWriterHandle = await IData.NewSelfEncryptorAsync();
await IData.WriteToSelfEncryptorAsync(seWriterHandle, payload.ToList());
var dataMapAddress = await IData.CloseSelfEncryptorAsync(seWriterHandle, cipherOptHandle);
//await IData.SelfEncryptorWriterFreeAsync(seWriterHandle); <= commented out since I couldn't free after having closed on the line before..
return dataMapAddress;
}
I feel like I’m missing information about how this should be done. Because I am doing something wrong here, which corrupts memory somehow, making a mess with returned pointers, or no?
Should we close a writer, but not free it? Or free it but not close, or both? (well, both did not work, I tried that)
And how about reader?