Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Manage Emulators automatically #55

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open

WIP: Manage Emulators automatically #55

wants to merge 16 commits into from

Conversation

zner0L
Copy link
Contributor

@zner0L zner0L commented Oct 28, 2024

We want to manage emulators automatically, create and delete them as needed and recover failure states (in doubt by creating new emulators on the fly).
This breaks some parts of the current API, but I took care not to change too much. If you think I should get rid of some legacy code, I am open for doing it with this PR, too.

Depends on tweaselORG/appstraction#137 and tweaselORG/appstraction#140 to be released to merge.

Copy link
Member

@baltpeter baltpeter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tested this yet since snapshot management isn't fully implemented yet, but I really like the direction this is going!

I could also definitely see the AndroidEmulator class being useful in other contexts, so maybe we should move that to andromatic at some point? But we don't have the time for that now.

README.md Outdated Show resolved Hide resolved
src/version.gen.ts Outdated Show resolved Hide resolved
src/emulator.ts Show resolved Hide resolved
src/emulator.ts Outdated

export const listSnapshots = async (): Promise<{ [name: string]: string[] }> => {
// This returns a list of snapshots of all devices
const { stdout } = await runAndroidDevTool('emulator', ['-snapshot-list']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that need a specific emu version?

❯ emulator -snapshot-list
INFO    | Android emulator version 32.1.12.0 (build_id 9751036) (CL:N/A)
ERROR   | No AVD specified. Use '@foo' or '-avd foo' to launch a virtual device named 'foo'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, at least for your version, this should be available, according to the documentation close to the release date. I am using 35.2.10.0, though. Have you set the correct ANDROID_HOME?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snippet above was using my system emu (with correct ANDROID_HOME). Doesn't work with the andromatic one, either:

export ANDROID_HOME=~/.cache/andromatic/
❯ ~/.cache/andromatic/emulator/emulator -snapshot-list
INFO    | Android emulator version 33.1.24.0 (build_id 11237101) (CL:N/A)
ERROR   | No AVD specified. Use '@foo' or '-avd foo' to launch a virtual device named 'foo'

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the docs are wrong then. Just tested on my Macbook where I have version 32 as well and got the same error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifying an AVD name as in the docs you linked starts the emu and doesn't list the snapshots:

❯ ~/.cache/andromatic/emulator/emulator @mitm11-honey -snapshot-list
INFO    | Android emulator version 33.1.24.0 (build_id 11237101) (CL:N/A)
INFO    | Found systemPath /home/benni/.cache/andromatic//system-images/android-30/google_apis/x86_64/
INFO    | Storing crashdata in: , detection is enabled for process: 1494826
INFO    | Duplicate loglines will be removed, if you wish to see each individual line launch with the -log-nofilter flag.
WARNING | Please update the emulator to one that supports the feature(s): Vulkan
INFO    | Increasing RAM size to 2048MB
WARNING | FeatureControl is requesting a non existing feature.
Fontconfig warning: "/usr/share/fontconfig/conf.avail/05-reset-dirs-sample.conf", line 6: unknown element "reset-dirs"
library_mode host gpu mode host
I1125 13:52:53.193065 1494826 HealthMonitor.cpp:279] HealthMonitor disabled.
cannot add library libvulkan.so: failed
added library libvulkan.so.1
createGlobalVkEmulation:963 Selecting Vulkan device: NVIDIA GeForce RTX 2060
initialize: Supports id properties, got a vulkan device UUID
I1125 13:52:53.423908 1494826 VkCommonOperations.cpp:1225] Initializing VkEmulation features:
I1125 13:52:53.423929 1494826 VkCommonOperations.cpp:1226]     glInteropSupported: true
I1125 13:52:53.423936 1494826 VkCommonOperations.cpp:1227]     useDeferredCommands: true
I1125 13:52:53.423944 1494826 VkCommonOperations.cpp:1229]     createResourceWithRequirements: true
I1125 13:52:53.423952 1494826 VkCommonOperations.cpp:1230]     useVulkanComposition: false
I1125 13:52:53.423958 1494826 VkCommonOperations.cpp:1231]     useVulkanNativeSwapchain: false
I1125 13:52:53.423964 1494826 VkCommonOperations.cpp:1232]     enable guestRenderDoc: false
I1125 13:52:53.423970 1494826 VkCommonOperations.cpp:1233]     ASTC LDR emulation mode: 2
I1125 13:52:53.423977 1494826 VkCommonOperations.cpp:1234]     enable ETC2 emulation: true
I1125 13:52:53.423982 1494826 VkCommonOperations.cpp:1235]     enable Ycbcr emulation: false
I1125 13:52:53.423988 1494826 VkCommonOperations.cpp:1236]     guestUsesAngle: false
I1125 13:52:53.423995 1494826 VkCommonOperations.cpp:1237]     useDedicatedAllocations: false
I1125 13:52:53.425509 1494826 FrameBuffer.cpp:486] Graphics Adapter Vendor Google (NVIDIA Corporation)
I1125 13:52:53.425517 1494826 FrameBuffer.cpp:487] Graphics Adapter Android Emulator OpenGL ES Translator (NVIDIA GeForce RTX 2060/PCIe/SSE2)
I1125 13:52:53.425523 1494826 FrameBuffer.cpp:488] Graphics API Version OpenGL ES 3.0 (4.5.0 NVIDIA 535.183.01)
I1125 13:52:53.425541 1494826 FrameBuffer.cpp:489] Graphics API Extensions GL_OES_EGL_sync GL_OES_EGL_image GL_OES_EGL_image_external GL_OES_depth24 GL_OES_depth32 GL_OES_element_index_uint GL_OES_texture_float GL_OES_texture_float_linear GL_OES_compressed_paletted_texture GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth_texture GL_OES_texture_half_float GL_OES_texture_half_float_linear GL_OES_packed_depth_stencil GL_OES_vertex_half_float GL_OES_texture_npot GL_OES_rgb8_rgba8 GL_EXT_color_buffer_float GL_EXT_color_buffer_half_float GL_EXT_texture_format_BGRA8888 GL_APPLE_texture_format_BGRA8888 GL_EXT_texture_buffer 
I1125 13:52:53.425551 1494826 FrameBuffer.cpp:490] Graphics Device Extensions N/A
WARNING | The emulator now requires a signed jwt token for gRPC access! Use the -grpc flag if you really want an open unprotected grpc port
INFO    | Using security allow list from: /home/benni/.cache/andromatic/emulator/lib/emulator_access.json
WARNING | *** Basic token auth should only be used by android-studio ***
INFO    | The active JSON Web Key Sets can be found here: /run/user/1000/avd/running/1494826/jwks/d41f381f-cacb-409b-9689-b47fcd8dfa97/active.jwk
INFO    | Scanning /run/user/1000/avd/running/1494826/jwks/d41f381f-cacb-409b-9689-b47fcd8dfa97 for jwk keys.
INFO    | Started GRPC server at 127.0.0.1:8554, security: Local, auth: +token
INFO    | Advertising in: /run/user/1000/avd/running/pid_1494826.ini
List of snapshots present on all disks:
ID        TAG                 VM SIZE                DATE       VM CLOCK
--        default_boot           1.1M 2024-11-25 13:52:40   00:00:04.588
I1125 13:52:53.648558 1494867 FrameBuffer.cpp:3682] setDisplayConfigs w 1080 h 1920 dpiX 420 dpiY 420
I1125 13:52:53.648601 1494867 FrameBuffer.cpp:3695] setDisplayActiveConfig 0
INFO    | Loading snapshot 'default_boot'...
INFO    | Successfully loaded snapshot 'default_boot'
INFO    | Info: Sandboxing disabled by user. ((null):0, (null))
INFO    | Wait for emulator (pid 1494826) 20 seconds to shutdown gracefully before kill;you can set environment variable ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL(in seconds) to change the default value (20 seconds)
[1494826:1495037:1125/135257.138795:ERROR:nss_util.cc(748)] After loading Root Certs, loaded==false: NSS error code: -8018
INFO    | Critical: Uncaught SyntaxError: Unexpected token . (https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyABrfflV49aFWF4Kohsf1VSx68td8f-sFY&callback=initMap&v=3.53:30, (null))
INFO    | Saving with gfxstream=1
INFO    | Critical: Uncaught SyntaxError: Unexpected token . (https://maps.googleapis.com/maps/api/js?libraries=places&key=AIzaSyABrfflV49aFWF4Kohsf1VSx68td8f-sFY&callback=initMap&v=3.53:30, (null))
ERROR   | stop: Not implemented

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s hard to tell, there is a -no-snapstorage options, but I don’t care to test this. I guess I’ll just use the folders as a fallback?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But again, there is no way to pass to pass any of these options to CA anyway, is there?

Copy link
Contributor Author

@zner0L zner0L Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, no. We also don’t use this function right now, so maybe I shouldn’t care really? As I said in the comment, I don’t know if I really want to introduce the added complexity of snapshot management anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said in the comment, I don’t know if I really want to introduce the added complexity of snapshot management anyway.

But you included most of that already, how much more is there to do? Also, we decided to move the honey data automation from cli to CA.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs to be addressed.

src/emulator.ts Outdated Show resolved Hide resolved
src/util.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
examples/multiple-apps.ts Outdated Show resolved Hide resolved
examples/multiple-apps.ts Show resolved Hide resolved
@zner0L zner0L requested a review from baltpeter November 27, 2024 14:56
Copy link
Member

@baltpeter baltpeter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, but as I've said before, I don't think it can be merged without snapshot management.

src/index.ts Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
src/emulator.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
src/emulator.ts Outdated Show resolved Hide resolved
@zner0L zner0L requested a review from baltpeter November 30, 2024 00:12
src/index.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
src/index.ts Outdated Show resolved Hide resolved
@zner0L zner0L requested a review from baltpeter December 11, 2024 14:54
Copy link
Member

@baltpeter baltpeter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've now actually tested this instead of just reading the code. While doing that, I also did a few minor changes (mostly docs) in 9340ee4.

The README now mentions the emu management feature but doesn't tell you anything about how to use it. I've added an example to at least partly address that (needs more comments, though), but I still think that this also needs to be addressed in the README. I can do that if you don't want to.

Other than that, I did unfortunately still encounter issues where the automatic recovery didn't work, see below.

// }
} catch (error: any) {
// Handle the error here, e.g. queue the app for analysis again etc.
if (error.name === 'EmulatorError') console.error(error.message);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handling EmulatorError isn't enough. Here's what I got when closing the emulator during an analysis (having added an else throw error;):

file:///home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/node_modules/andromatic/node_modules/execa/lib/error.js:59
		error = new Error(message);
		        ^

Error: Command failed with exit code 1: /home/benni/.cache/andromatic/platform-tools/adb root
adb: unable to connect for root: device offline
    at makeError (file:///home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/node_modules/andromatic/node_modules/execa/lib/error.js:59:11)
    at handlePromise (file:///home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/node_modules/andromatic/node_modules/execa/index.js:124:26)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at Object.requireRoot (/home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/src/android.ts:299:17)
    at Object.overlayTmpfs (/home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/src/android.ts:339:38)
    at Object.removeCertificateAuthority (/home/benni/coding/JS/tweasel/cyanoacrylate/node_modules/appstraction/src/android.ts:841:9)
    at <anonymous> (/home/benni/coding/JS/tweasel/cyanoacrylate/src/index.ts:652:17)
    at async Promise.all (index 0)
    at stopTrafficCollection (/home/benni/coding/JS/tweasel/cyanoacrylate/src/index.ts:634:23)
    at Object.stopTrafficCollection (/home/benni/coding/JS/tweasel/cyanoacrylate/src/index.ts:863:33) {
  shortMessage: 'Command failed with exit code 1: /home/benni/.cache/andromatic/platform-tools/adb root',
  command: '/home/benni/.cache/andromatic/platform-tools/adb root',
  escapedCommand: '"/home/benni/.cache/andromatic/platform-tools/adb" root',
  exitCode: 1,
  signal: undefined,
  signalDescription: undefined,
  stdout: '',
  stderr: 'adb: unable to connect for root: device offline',
  failed: true,
  timedOut: false,
  isCanceled: false,
  killed: false
}

@@ -0,0 +1,289 @@
import {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Recovery from broken snapshots doesn't seem to be handled. I deleted the snapshot (by deleting the folder in ~/.android/avd/cyanoacrylate-examples-multiple-apps-9a2f000670072430e8fe9f968a2a1d15.avd/snapshots) while an analysis was running. The analysis for the current app finished without issues, but every subsequent app failed:

Analyzing com.airbnb.android-28003318.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: different renderer configured.
Analyzing com.apprope.wordsearch-192.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: different renderer configured.
Analyzing com.booking-24681.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: different renderer configured.
Analyzing com.digibites.accubattery-201004.apk…

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After restarting the analysis program, it did recover.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue when corrupting the emulator itself by deleting userdata-qemu.img:

Analyzing com.airbnb.android-28003318.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.apprope.wordsearch-192.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.booking-24681.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.digibites.accubattery-201004.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.easybrain.block.puzzle.games-22101001.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.flightradar24free-91902797.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.gsoftteam.connectbubbles-216313.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.hbwares.wordfeud.free-4242.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.kiloo.subwaysurf-69038.apk…
Ensuring device…
(node:2294899) MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal]. Use events.setMaxListeners() to increase limit
(Use `node --trace-warnings ...` to show where the warning was created)
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.monefy.app.lite-2207.apk…
Ensuring device…
Failed to load snapshot: KO: Error -1 from the snapshot callback
KO: Snapshot load failure: system image changed.
Analyzing com.motionvolt.flipdiving-10103660.apk…
Ensuring device…
^C%                                                                                                                                              

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one didn't even recover after restarting the analysis program:

❯ tsx examples/multiple-apps.ts ~/Downloads/test-complaints/
Analyzing be.stib.mivb.mobile-203137.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.airbnb.android-28003318.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.apprope.wordsearch-192.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.booking-24681.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.digibites.accubattery-201004.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.easybrain.block.puzzle.games-22101001.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.flightradar24free-91902797.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.gsoftteam.connectbubbles-216313.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.hbwares.wordfeud.free-4242.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.kiloo.subwaysurf-69038.apk…
Ensuring device…
(node:2327458) MaxListenersExceededWarning: Possible EventTarget memory leak detected. 11 abort listeners added to [AbortSignal]. Use events.setMaxListeners() to increase limit
(Use `node --trace-warnings ...` to show where the warning was created)
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.monefy.app.lite-2207.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.motionvolt.flipdiving-10103660.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.sparklingsociety.cityisland5-85898.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.viber.voip-651257.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing com.yopeso.lieferando-1610000497.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing de.mobileconcepts.cyberghost-2925.apk…
Ensuring device…
Failed to load snapshot: KO: Device 'cache' does not have the requested snapshot 'cyanoacrylate-ensured'
KO: Snapshot load failure: snapshot doesn't exist.
Analyzing har…
Ensuring device…
^C

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snapshot does exist though, despite the error message:

❯ tree /home/benni/.android/avd/cyanoacrylate-examples-multiple-apps-9a2f000670072430e8fe9f968a2a1d15.avd/snapshots
/home/benni/.android/avd/cyanoacrylate-examples-multiple-apps-9a2f000670072430e8fe9f968a2a1d15.avd/snapshots
├── cyanoacrylate-ensured
│   ├── hardware.ini
│   ├── ram.bin
│   ├── screenshot.png
│   ├── snapshot.pb
│   └── textures.bin
└── default_boot
    ├── ram.img
    └── snapshot.pb

3 directories, 7 files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, figures. If adb realizes that the snapshot is broken before it sends it off to the emu, it doesn’t register an error.

src/emulator.ts Outdated

export const listSnapshots = async (): Promise<{ [name: string]: string[] }> => {
// This returns a list of snapshots of all devices
const { stdout } = await runAndroidDevTool('emulator', ['-snapshot-list']);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs to be addressed.

@@ -1,3 +1,4 @@
import type { EmulatorOptions } from 'andromatic';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ctrl + Cing the analysis program sometimes works, but sometimes it doesn't do anything.

I'd guess we need to update our SIGINT handler?

And while you're at it, we should also only remove our handler instead of doing removeAllListeners(), which would remove the need for the noSigint option.

@zner0L zner0L requested a review from baltpeter December 16, 2024 18:16
@zner0L
Copy link
Contributor Author

zner0L commented Dec 16, 2024

I addressed and tested everything again, please check it out and also merge tweaselORG/appstraction#140, @baltpeter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants