Skip to content

disconnecting ktsignal_connection inside its callback execution crashes the program #20

@Aldrin-John-Olaer-Manalansan

Description

void setuphooks(bool newStatus) {
    static kthook::kthook_signal<void(CCDECL *)(void)> gameLoop_Hook(0x53BFC7, false);
    static decltype(gameLoop_Hook.before)::ktsignal_connection gameloop_Before = {[](){}};
    static decltype(gameLoop_Hook.after)::ktsignal_connection gameloop_After = {[](){}};
	
    static kthook::kthook_signal<bool(CTHISCALL *)(CPed *thisPtr)> uponFiringEvent_Hook(0x7427C9, false);
    static decltype(uponFiringEvent_Hook.before)::ktsignal_connection uponFiringEvent_Before = {[](){}};
    static decltype(uponFiringEvent_Hook.after)::ktsignal_connection uponFiringEvent_After = {[](){}};

	static bool currentStatus;
	if (currentStatus == newStatus) {
		return; // no change
	}
	currentStatus = newStatus;
	if (!newStatus) {
		gameloop_Before.disconnect(); // works if outside its own callback
		gameloop_After.disconnect(); // works if outside its own callback
		uponFiringEvent_Before.disconnect(); // works if outside its own callback
		uponFiringEvent_After.disconnect(); // works if outside its own callback
		printf("Works\n");
		return;
	}
	
    gameloop_Before = gameLoop_Hook.before.connect([](const auto &whichHook) {
		gameloop_Before.disconnect(); // crashes the program
		printf("gameloop_Before will crash the program\n");
		return true;
    });

    gameloop_After = gameLoop_Hook.after.connect([](const auto &whichHook) {
		gameloop_After.disconnect(); // crashes the program
		printf("gameloop_After will crash the program\n");
    });
	
    uponFiringEvent_Before = uponFiringEvent_Hook.before.connect([](const auto &whichHook, CPed *thisPtr) -> std::optional<bool> {
		uponFiringEvent_Before.disconnect(); // crashes the program
		printf("uponFiringEvent_Before will crash the program\n");
		return std::nullopt;
    });

    uponFiringEvent_After = uponFiringEvent_Hook.after.connect([](const auto &whichHook, bool &retVal, CPed *thisPtr) {
		uponFiringEvent_After.disconnect(); // crashes the program
		printf("uponFiringEvent_After will crash the program\n");
    });
}

I'm fully aware that kthook_simple is the best choice for the code above. But this is just a mock test to get the idea of what I'm talking about.




kthook_simple does not have any issue disconnecting itself while its own callback is executing:

void setupsimplehooks(bool newStatus) {
	using gameLoop_SimpleHookType = kthook::kthook_simple<void(CCDECL *)(void)>;
	static gameLoop_SimpleHookType gameLoop_SimpleHook(
		0x53BFC7,
		[](const gameLoop_SimpleHookType &whichHook) {
			auto &nonConstHook = const_cast<gameLoop_SimpleHookType&>(whichHook);
			nonConstHook.remove(); // disconnect hook
			printf("gameLoop_SimpleHook disconnect Works inside its own callback");
			whichHook.call_trampoline(); // call original
		}, false);

	using uponFiringEvent_SimpleHookType = kthook::kthook_simple<bool(CTHISCALL *)(CPed *thisPtr)>;
	static uponFiringEvent_SimpleHookType uponFiringEvent_SimpleHook(
		0x7427C9,
		[](const uponFiringEvent_SimpleHookType &whichHook, CPed *thisPtr) -> bool {
			auto &nonConstHook = const_cast<uponFiringEvent_SimpleHookType&>(whichHook);
			nonConstHook.remove(); // disconnect hook
			printf("uponFiringEvent_SimpleHook disconnect Works inside its own callback");
			return whichHook.call_trampoline(thisPtr); // call original
		}, false);

	static bool currentStatus;
	if (currentStatus == newStatus) {
		return; // no change
	}
	if (!newStatus) {
	        gameLoop_SimpleHook.remove();
	        uponFiringEvent_SimpleHook.remove();
		printf("simplehook disconnect outside its own callback Works\n");
		return;
	}
	gameLoop_SimpleHook.install();
	uponFiringEvent_SimpleHook.install();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions