Skip to content

Commit c8c65f4

Browse files
authored
Fix short lived callback lifetimes (#90)
Signed-off-by: Kristupas Antanavičius <[email protected]>
1 parent f119684 commit c8c65f4

File tree

5 files changed

+32
-16
lines changed

5 files changed

+32
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### UNRELEASED
2+
3+
- **IMPORTANT**: Fix short-lived callback lifetimes (#79)
4+
15
### v0.8.2+v0.25.0
26

37
- Update C# callback syntax to work on iOS (#84)

bindgen/templates/CallbackInterfaceRuntime.cs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,25 @@ static class UniffiCallbackResponseCode {
99
}
1010

1111
class ConcurrentHandleMap<T> where T: notnull {
12-
Dictionary<ulong, T> leftMap = new Dictionary<ulong, T>();
13-
Dictionary<T, ulong> rightMap = new Dictionary<T, ulong>();
12+
Dictionary<ulong, T> map = new Dictionary<ulong, T>();
1413

1514
Object lock_ = new Object();
1615
ulong currentHandle = 0;
1716

1817
public ulong Insert(T obj) {
1918
lock (lock_) {
20-
ulong existingHandle = 0;
21-
if (rightMap.TryGetValue(obj, out existingHandle)) {
22-
return existingHandle;
23-
}
2419
currentHandle += 1;
25-
leftMap[currentHandle] = obj;
26-
rightMap[obj] = currentHandle;
20+
map[currentHandle] = obj;
2721
return currentHandle;
2822
}
2923
}
3024

3125
public bool TryGet(ulong handle, out T result) {
32-
// Possible null reference assignment
33-
#pragma warning disable 8601
34-
return leftMap.TryGetValue(handle, out result);
35-
#pragma warning restore 8601
26+
lock (lock_) {
27+
#pragma warning disable 8601 // Possible null reference assignment
28+
return map.TryGetValue(handle, out result);
29+
#pragma warning restore 8601
30+
}
3631
}
3732

3833
public bool Remove(ulong handle) {
@@ -43,10 +38,9 @@ public bool Remove(ulong handle, out T result) {
4338
lock (lock_) {
4439
// Possible null reference assignment
4540
#pragma warning disable 8601
46-
if (leftMap.TryGetValue(handle, out result)) {
41+
if (map.TryGetValue(handle, out result)) {
4742
#pragma warning restore 8601
48-
leftMap.Remove(handle);
49-
rightMap.Remove(result);
43+
map.Remove(handle);
5044
return true;
5145
} else {
5246
return false;

dotnet-tests/UniffiCS.BindingTests/TestCallbacksFixture.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,4 +189,20 @@ public void VoidCallbackExceptions()
189189
);
190190
}
191191
}
192+
193+
[Fact]
194+
public void ShortLivedCallbackDoesNotInvalidateLongerLivedCallback()
195+
{
196+
var stringifier = new CsharpStringifier();
197+
using (var rustStringifier1 = new RustStringifier(stringifier))
198+
{
199+
using (var rustStringifier2 = new RustStringifier(stringifier))
200+
{
201+
Assert.Equal("C#: 123", rustStringifier2.FromSimpleType(123));
202+
}
203+
// `stringifier` must remain valid after `rustStringifier2` drops the reference
204+
205+
Assert.Equal("C#: 123", rustStringifier1.FromSimpleType(123));
206+
}
207+
}
192208
}

dotnet-tests/UniffiCS.BindingTests/TestNullToEmptyString.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public class TestNullToEmptyString
1212
public void NullToEmptyStringWorks()
1313
{
1414
Assert.Equal("hello", LibGreeter.HelloWorld("hello"));
15+
#pragma warning disable 8625 // Cannot convert null literal to non-nullable reference type
1516
Assert.Equal("", LibGreeter.HelloWorld(null));
17+
#pragma warning restore 8625
1618
}
1719
}

generate_bindings.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ GEN_DIR="dotnet-tests/UniffiCS/gen"
66
rm -rf "$GEN_DIR"
77
mkdir -p "$GEN_DIR"
88

9-
target/debug/uniffi-bindgen-cs target/debug/libuniffi_fixtures.so --library --out-dir="$GEN_DIR"
9+
target/debug/uniffi-bindgen-cs target/debug/libuniffi_fixtures.so --library --out-dir="$GEN_DIR" --no-format

0 commit comments

Comments
 (0)