Commit 77d26ee
fix(google): prevent double-resume crash in purchase flow (#95)
## Summary
- Replace the mutable `currentPurchaseCallback` var in both Play and
Horizon `OpenIapModule` with an `AtomicReference`, and route every
invocation through a new `consumePurchaseCallback()` helper that
atomically swaps the slot to `null` before invoking — guaranteeing the
underlying `suspendCancellableCoroutine` continuation can be resumed at
most once.
- Clear the callback slot on continuation cancellation so a late billing
event can't resume a cancelled coroutine.
Closes #94
## Root cause
`requestPurchase` stored the resume lambda in a shared mutable field and
only nulled it out at the end of `onPurchasesUpdated`. Between the
invocation and the clear:
- `onPurchasesUpdated` could fire again (Play Billing is known to
deliver duplicate updates), or
- a re-entrant / racing callback could observe the still-set lambda and
call it a second time, or
- an early-return path inside `requestPurchase` could invoke the
callback without nulling the slot, leaving it primed for a stale event
later.
The lambda's `if (continuation.isActive)` guard is not atomic with
`resume()`, so two callers could both pass the check and both call
`resume()` — producing the observed `IllegalStateException: Already
resumed`. Making the slot single-shot via
`AtomicReference.getAndSet(null)` eliminates the window entirely.
## Test plan
- [x] `./gradlew :openiap:compilePlayDebugKotlin
:openiap:compileHorizonDebugKotlin` passes
- [ ] Verify a normal purchase flow still resolves (manual smoke on a
debug build)
- [ ] Verify rapid double-tap of `requestPurchase` no longer crashes
🤖 Generated with [Claude Code](https://claude.ai/code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Improved internal robustness of purchase callback handling for more
reliable operation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent d1c1253 commit 77d26ee
3 files changed
Lines changed: 71 additions & 35 deletions
File tree
- .claude/commands
- packages/google/openiap/src
- horizon/java/dev/hyo/openiap
- play/java/dev/hyo/openiap
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
130 | 130 | | |
131 | 131 | | |
132 | 132 | | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
133 | 145 | | |
134 | 146 | | |
135 | 147 | | |
| |||
Lines changed: 29 additions & 20 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
| 52 | + | |
52 | 53 | | |
53 | 54 | | |
54 | 55 | | |
| |||
97 | 98 | | |
98 | 99 | | |
99 | 100 | | |
100 | | - | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
101 | 111 | | |
102 | 112 | | |
103 | 113 | | |
| |||
370 | 380 | | |
371 | 381 | | |
372 | 382 | | |
373 | | - | |
| 383 | + | |
374 | 384 | | |
375 | 385 | | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
376 | 392 | | |
377 | 393 | | |
378 | 394 | | |
| |||
421 | 437 | | |
422 | 438 | | |
423 | 439 | | |
424 | | - | |
| 440 | + | |
425 | 441 | | |
426 | 442 | | |
427 | 443 | | |
| |||
437 | 453 | | |
438 | 454 | | |
439 | 455 | | |
440 | | - | |
| 456 | + | |
441 | 457 | | |
442 | 458 | | |
443 | 459 | | |
| |||
502 | 518 | | |
503 | 519 | | |
504 | 520 | | |
505 | | - | |
| 521 | + | |
506 | 522 | | |
507 | 523 | | |
508 | 524 | | |
| |||
524 | 540 | | |
525 | 541 | | |
526 | 542 | | |
527 | | - | |
| 543 | + | |
528 | 544 | | |
529 | 545 | | |
530 | 546 | | |
| |||
540 | 556 | | |
541 | 557 | | |
542 | 558 | | |
543 | | - | |
| 559 | + | |
544 | 560 | | |
545 | 561 | | |
546 | 562 | | |
| |||
560 | 576 | | |
561 | 577 | | |
562 | 578 | | |
563 | | - | |
| 579 | + | |
564 | 580 | | |
565 | 581 | | |
566 | 582 | | |
| |||
578 | 594 | | |
579 | 595 | | |
580 | 596 | | |
581 | | - | |
| 597 | + | |
582 | 598 | | |
583 | 599 | | |
584 | 600 | | |
| |||
856 | 872 | | |
857 | 873 | | |
858 | 874 | | |
859 | | - | |
860 | | - | |
861 | | - | |
862 | | - | |
863 | | - | |
| 875 | + | |
| 876 | + | |
864 | 877 | | |
865 | 878 | | |
866 | 879 | | |
867 | | - | |
868 | | - | |
869 | | - | |
870 | | - | |
| 880 | + | |
871 | 881 | | |
872 | 882 | | |
873 | 883 | | |
874 | 884 | | |
875 | 885 | | |
876 | | - | |
| 886 | + | |
877 | 887 | | |
878 | | - | |
879 | 888 | | |
880 | 889 | | |
881 | 890 | | |
| |||
Lines changed: 30 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
| |||
109 | 110 | | |
110 | 111 | | |
111 | 112 | | |
112 | | - | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
113 | 123 | | |
114 | 124 | | |
115 | 125 | | |
| |||
850 | 860 | | |
851 | 861 | | |
852 | 862 | | |
853 | | - | |
| 863 | + | |
854 | 864 | | |
855 | 865 | | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
856 | 872 | | |
857 | 873 | | |
858 | 874 | | |
| |||
878 | 894 | | |
879 | 895 | | |
880 | 896 | | |
881 | | - | |
| 897 | + | |
882 | 898 | | |
883 | 899 | | |
884 | 900 | | |
| |||
915 | 931 | | |
916 | 932 | | |
917 | 933 | | |
918 | | - | |
| 934 | + | |
919 | 935 | | |
920 | 936 | | |
921 | 937 | | |
| |||
942 | 958 | | |
943 | 959 | | |
944 | 960 | | |
945 | | - | |
| 961 | + | |
946 | 962 | | |
947 | 963 | | |
948 | 964 | | |
949 | 965 | | |
950 | 966 | | |
951 | 967 | | |
952 | 968 | | |
953 | | - | |
| 969 | + | |
954 | 970 | | |
955 | 971 | | |
956 | 972 | | |
| |||
1034 | 1050 | | |
1035 | 1051 | | |
1036 | 1052 | | |
1037 | | - | |
| 1053 | + | |
1038 | 1054 | | |
1039 | 1055 | | |
1040 | 1056 | | |
| |||
1044 | 1060 | | |
1045 | 1061 | | |
1046 | 1062 | | |
1047 | | - | |
| 1063 | + | |
1048 | 1064 | | |
1049 | 1065 | | |
1050 | 1066 | | |
| |||
1070 | 1086 | | |
1071 | 1087 | | |
1072 | 1088 | | |
1073 | | - | |
| 1089 | + | |
1074 | 1090 | | |
1075 | 1091 | | |
1076 | 1092 | | |
1077 | 1093 | | |
1078 | 1094 | | |
1079 | 1095 | | |
1080 | | - | |
| 1096 | + | |
1081 | 1097 | | |
1082 | 1098 | | |
1083 | 1099 | | |
| |||
1334 | 1350 | | |
1335 | 1351 | | |
1336 | 1352 | | |
1337 | | - | |
| 1353 | + | |
1338 | 1354 | | |
1339 | 1355 | | |
1340 | 1356 | | |
1341 | | - | |
| 1357 | + | |
1342 | 1358 | | |
1343 | 1359 | | |
1344 | 1360 | | |
1345 | 1361 | | |
1346 | 1362 | | |
1347 | 1363 | | |
1348 | | - | |
| 1364 | + | |
1349 | 1365 | | |
1350 | 1366 | | |
1351 | 1367 | | |
| |||
1354 | 1370 | | |
1355 | 1371 | | |
1356 | 1372 | | |
1357 | | - | |
| 1373 | + | |
1358 | 1374 | | |
1359 | 1375 | | |
1360 | 1376 | | |
1361 | | - | |
1362 | 1377 | | |
1363 | 1378 | | |
1364 | 1379 | | |
| |||
0 commit comments