Skip to content

Commit 2ff72d7

Browse files
authored
[monodroid] Prevent overlapped decompression of embedded assemblies (#7732)
Fixes: #7335 Context: d236af5 Commit d236af5 introduced embedded assembly compression, using LZ4, which speeds up startup and reduces final package size. Assemblies are compressed at build time and, at the same time, pre- allocated buffers for the **decompressed** data are allocated in `libxamarin-app.so`. The buffers are then passed to the LZ4 APIs, all threads using the same output buffer. The assumption was that we can do fine without locking as even if overlapped decompression happens, the output data will be the same and so even if two threads do the same thing at the same time, the data will be valid at all times, so long as at least one thread completes the decompression. This assumption proved to be **largely** true, but it appears that in high concurrency cases it is possible that the data in the decompression buffer differs. This can result in app crashes: A/libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 3092 (.NET ThreadPool), pid 2727 (myapp.name) A/DEBUG: pid: 2727, tid: 3092, name: .NET ThreadPool >>> myapp.name <<< A/DEBUG: #1 pc 0000000000029b1c /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmono-android.release.so (offset 0x103d000) (xamarin::android::internal::MonodroidRuntime::mono_log_handler(char const*, char const*, char const*, int, void*)+144) (BuildId: 29c5a3805a0bedee1eede9b6668d7c676aa63371) A/DEBUG: #2 pc 00000000002680bc /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b) A/DEBUG: #3 pc 00000000002681e8 /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b) A/DEBUG: #4 pc 000000000008555c /data/app/myapp.name-B9t_3dF9i8mDxJEKodZw5w==/split_config.arm64_v8a.apk!libmonosgen-2.0.so (offset 0x109b000) (mono_metadata_string_heap+188) (BuildId: 4a5dd4396e8816b7f69881838bd549285213d53b) … My guess is that LZ4 either uses the output buffer as a scratchpad area when decompressing or that it initializes/modifies the buffer before writing actual data in it. With overlapped decompression, it may lead to one thread overwriting valid data previously written by another thread, so that when the latter returns the buffer it thought to have had valid data may contain certain bytes temporarily overwritten by the decompression session in the other, still running, thread. It may happen that MonoVM reads the corrupted data just when it is still invalid (before the still running decompression session actually writes the valid data), a classic race condition. To fix this, the decompression block is now protected with a startup- aware mutex. Mutex will be held only after the initial startup phase is completed, so there should not be much loss of startup performance.
1 parent f04671a commit 2ff72d7

File tree

6 files changed

+86
-83
lines changed

6 files changed

+86
-83
lines changed

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.apkdesc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
"Size": 1024
99
},
1010
"assemblies/Java.Interop.dll": {
11-
"Size": 58916
11+
"Size": 58913
1212
},
1313
"assemblies/Mono.Android.dll": {
14-
"Size": 87170
14+
"Size": 87106
1515
},
1616
"assemblies/Mono.Android.Runtime.dll": {
17-
"Size": 5931
17+
"Size": 5860
1818
},
1919
"assemblies/rc.bin": {
2020
"Size": 1182
@@ -35,7 +35,7 @@
3535
"Size": 2265
3636
},
3737
"assemblies/UnnamedProject.dll": {
38-
"Size": 3257
38+
"Size": 3258
3939
},
4040
"classes.dex": {
4141
"Size": 19020
@@ -44,7 +44,7 @@
4444
"Size": 93552
4545
},
4646
"lib/arm64-v8a/libmonodroid.so": {
47-
"Size": 434704
47+
"Size": 379320
4848
},
4949
"lib/arm64-v8a/libmonosgen-2.0.so": {
5050
"Size": 3089272
@@ -59,7 +59,7 @@
5959
"Size": 152960
6060
},
6161
"lib/arm64-v8a/libxamarin-app.so": {
62-
"Size": 16760
62+
"Size": 16720
6363
},
6464
"META-INF/BNDLTOOL.RSA": {
6565
"Size": 1213
@@ -95,5 +95,5 @@
9595
"Size": 1904
9696
}
9797
},
98-
"PackageSize": 2648394
98+
"PackageSize": 2632010
9999
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@
55
"Size": 2604
66
},
77
"assemblies/Java.Interop.dll": {
8-
"Size": 68923
8+
"Size": 68913
99
},
1010
"assemblies/Mono.Android.dll": {
11-
"Size": 265140
11+
"Size": 265170
1212
},
1313
"assemblies/mscorlib.dll": {
14-
"Size": 769036
14+
"Size": 769019
1515
},
1616
"assemblies/System.Core.dll": {
17-
"Size": 28216
17+
"Size": 28199
1818
},
1919
"assemblies/System.dll": {
20-
"Size": 9192
20+
"Size": 9180
2121
},
2222
"assemblies/UnnamedProject.dll": {
23-
"Size": 2897
23+
"Size": 2881
2424
},
2525
"classes.dex": {
2626
"Size": 370828
@@ -32,7 +32,7 @@
3232
"Size": 750976
3333
},
3434
"lib/arm64-v8a/libmonodroid.so": {
35-
"Size": 333128
35+
"Size": 277744
3636
},
3737
"lib/arm64-v8a/libmonosgen-2.0.so": {
3838
"Size": 4039176
@@ -41,7 +41,7 @@
4141
"Size": 66184
4242
},
4343
"lib/arm64-v8a/libxamarin-app.so": {
44-
"Size": 21264
44+
"Size": 21256
4545
},
4646
"META-INF/ANDROIDD.RSA": {
4747
"Size": 1213
@@ -74,5 +74,5 @@
7474
"Size": 1724
7575
}
7676
},
77-
"PackageSize": 4003540
77+
"PackageSize": 3987156
7878
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.apkdesc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,13 @@
1111
"Size": 7313
1212
},
1313
"assemblies/Java.Interop.dll": {
14-
"Size": 66790
14+
"Size": 66786
1515
},
1616
"assemblies/Mono.Android.dll": {
17-
"Size": 444768
17+
"Size": 444701
1818
},
1919
"assemblies/Mono.Android.Runtime.dll": {
20-
"Size": 5931
20+
"Size": 5860
2121
},
2222
"assemblies/mscorlib.dll": {
2323
"Size": 3863
@@ -206,7 +206,7 @@
206206
"Size": 93552
207207
},
208208
"lib/arm64-v8a/libmonodroid.so": {
209-
"Size": 434704
209+
"Size": 379320
210210
},
211211
"lib/arm64-v8a/libmonosgen-2.0.so": {
212212
"Size": 3089272
@@ -221,7 +221,7 @@
221221
"Size": 152960
222222
},
223223
"lib/arm64-v8a/libxamarin-app.so": {
224-
"Size": 333760
224+
"Size": 333720
225225
},
226226
"META-INF/android.support.design_material.version": {
227227
"Size": 12
@@ -1976,5 +1976,5 @@
19761976
"Size": 341228
19771977
}
19781978
},
1979-
"PackageSize": 7824132
1979+
"PackageSize": 7807748
19801980
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsLegacy.apkdesc

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,112 +5,112 @@
55
"Size": 3140
66
},
77
"assemblies/FormsViewGroup.dll": {
8-
"Size": 7230
8+
"Size": 7215
99
},
1010
"assemblies/Java.Interop.dll": {
11-
"Size": 69966
11+
"Size": 69955
1212
},
1313
"assemblies/Mono.Android.dll": {
14-
"Size": 572670
14+
"Size": 572710
1515
},
1616
"assemblies/Mono.Security.dll": {
17-
"Size": 68449
17+
"Size": 68432
1818
},
1919
"assemblies/mscorlib.dll": {
20-
"Size": 915425
20+
"Size": 915407
2121
},
2222
"assemblies/System.Core.dll": {
23-
"Size": 164059
23+
"Size": 164046
2424
},
2525
"assemblies/System.dll": {
26-
"Size": 388883
26+
"Size": 388865
2727
},
2828
"assemblies/System.Drawing.Common.dll": {
29-
"Size": 12370
29+
"Size": 12365
3030
},
3131
"assemblies/System.Net.Http.dll": {
32-
"Size": 110718
32+
"Size": 110693
3333
},
3434
"assemblies/System.Numerics.dll": {
35-
"Size": 15706
35+
"Size": 15683
3636
},
3737
"assemblies/System.Runtime.Serialization.dll": {
38-
"Size": 186683
38+
"Size": 186660
3939
},
4040
"assemblies/System.ServiceModel.Internals.dll": {
41-
"Size": 26604
41+
"Size": 26593
4242
},
4343
"assemblies/System.Xml.dll": {
44-
"Size": 395668
44+
"Size": 395657
4545
},
4646
"assemblies/UnnamedProject.dll": {
47-
"Size": 116997
47+
"Size": 116986
4848
},
4949
"assemblies/Xamarin.AndroidX.Activity.dll": {
50-
"Size": 7711
50+
"Size": 7697
5151
},
5252
"assemblies/Xamarin.AndroidX.AppCompat.AppCompatResources.dll": {
53-
"Size": 6664
53+
"Size": 6648
5454
},
5555
"assemblies/Xamarin.AndroidX.AppCompat.dll": {
56-
"Size": 125346
56+
"Size": 125328
5757
},
5858
"assemblies/Xamarin.AndroidX.CardView.dll": {
59-
"Size": 7380
59+
"Size": 7366
6060
},
6161
"assemblies/Xamarin.AndroidX.CoordinatorLayout.dll": {
62-
"Size": 18289
62+
"Size": 18272
6363
},
6464
"assemblies/Xamarin.AndroidX.Core.dll": {
65-
"Size": 131944
65+
"Size": 131930
6666
},
6767
"assemblies/Xamarin.AndroidX.DrawerLayout.dll": {
68-
"Size": 15443
68+
"Size": 15426
6969
},
7070
"assemblies/Xamarin.AndroidX.Fragment.dll": {
71-
"Size": 43150
71+
"Size": 43135
7272
},
7373
"assemblies/Xamarin.AndroidX.Legacy.Support.Core.UI.dll": {
74-
"Size": 6727
74+
"Size": 6715
7575
},
7676
"assemblies/Xamarin.AndroidX.Lifecycle.Common.dll": {
77-
"Size": 7078
77+
"Size": 7062
7878
},
7979
"assemblies/Xamarin.AndroidX.Lifecycle.LiveData.Core.dll": {
80-
"Size": 7208
80+
"Size": 7194
8181
},
8282
"assemblies/Xamarin.AndroidX.Lifecycle.ViewModel.dll": {
83-
"Size": 4886
83+
"Size": 4873
8484
},
8585
"assemblies/Xamarin.AndroidX.Loader.dll": {
86-
"Size": 13596
86+
"Size": 13585
8787
},
8888
"assemblies/Xamarin.AndroidX.RecyclerView.dll": {
89-
"Size": 102349
89+
"Size": 102326
9090
},
9191
"assemblies/Xamarin.AndroidX.SavedState.dll": {
92-
"Size": 6294
92+
"Size": 6268
9393
},
9494
"assemblies/Xamarin.AndroidX.SwipeRefreshLayout.dll": {
95-
"Size": 11284
95+
"Size": 11272
9696
},
9797
"assemblies/Xamarin.AndroidX.ViewPager.dll": {
98-
"Size": 19438
98+
"Size": 19424
9999
},
100100
"assemblies/Xamarin.Forms.Core.dll": {
101-
"Size": 524743
101+
"Size": 524736
102102
},
103103
"assemblies/Xamarin.Forms.Platform.Android.dll": {
104-
"Size": 384885
104+
"Size": 384872
105105
},
106106
"assemblies/Xamarin.Forms.Platform.dll": {
107107
"Size": 56878
108108
},
109109
"assemblies/Xamarin.Forms.Xaml.dll": {
110-
"Size": 55807
110+
"Size": 55801
111111
},
112112
"assemblies/Xamarin.Google.Android.Material.dll": {
113-
"Size": 43514
113+
"Size": 43497
114114
},
115115
"classes.dex": {
116116
"Size": 3533252
@@ -122,7 +122,7 @@
122122
"Size": 750976
123123
},
124124
"lib/arm64-v8a/libmonodroid.so": {
125-
"Size": 333128
125+
"Size": 277744
126126
},
127127
"lib/arm64-v8a/libmonosgen-2.0.so": {
128128
"Size": 4039176
@@ -131,7 +131,7 @@
131131
"Size": 66184
132132
},
133133
"lib/arm64-v8a/libxamarin-app.so": {
134-
"Size": 107032
134+
"Size": 107024
135135
},
136136
"META-INF/android.support.design_material.version": {
137137
"Size": 12
@@ -1883,5 +1883,5 @@
18831883
"Size": 341040
18841884
}
18851885
},
1886-
"PackageSize": 9537694
1886+
"PackageSize": 9521310
18871887
}

0 commit comments

Comments
 (0)