From 6c9e89be03c560e8a0961cdcde1ac700156c8534 Mon Sep 17 00:00:00 2001 From: caue Date: Mon, 30 Mar 2020 02:24:38 -0300 Subject: [PATCH] fixed segfault when starting and stoping the event hook too quickly, it was a data race --- event/goEvent.h | 93 +++++-------------------------------------------- extern.go | 1 + hook.go | 41 ++++++++++++++++++---- 3 files changed, 45 insertions(+), 90 deletions(-) diff --git a/event/goEvent.h b/event/goEvent.h index b0574e1..82f8a60 100644 --- a/event/goEvent.h +++ b/event/goEvent.h @@ -16,6 +16,9 @@ #include #include "pub.h" #include "../chan/eb_chan.h" + +void dispatch_proc(iohook_event * const event); + eb_chan events; void go_send(char*); @@ -24,10 +27,15 @@ void go_sleep(void); bool sending = false; void startev(){ + // puts("start_ev"); events = eb_chan_create(1024); eb_chan_retain(events); sending = true; - add_event("q"); + // add_event("q"); + hook_set_logger(&loggerProc); + hook_set_dispatch_proc(&dispatch_proc); + hook_run(); + // puts("done_ev"); } void pollEv(){ @@ -116,89 +124,6 @@ void dispatch_proc(iohook_event * const event) { // fprintf(stdout, "----%s\n", buffer); } -int add_event(char *key_event) { - cevent = key_event; - // Set the logger callback for library output. - hook_set_logger(&loggerProc); - - // Set the event callback for IOhook events. - hook_set_dispatch_proc(&dispatch_proc); - // Start the hook and block. - // NOTE If EVENT_HOOK_ENABLED was delivered, the status will always succeed. - int status = hook_run(); - - switch (status) { - case IOHOOK_SUCCESS: - // Everything is ok. - break; - - // System level errors. - case IOHOOK_ERROR_OUT_OF_MEMORY: - loggerProc(LOG_LEVEL_ERROR, "Failed to allocate memory. (%#X)", status); - break; - - - // X11 specific errors. - case IOHOOK_ERROR_X_OPEN_DISPLAY: - loggerProc(LOG_LEVEL_ERROR, "Failed to open X11 display. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_NOT_FOUND: - loggerProc(LOG_LEVEL_ERROR, "Unable to locate XRecord extension. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_ALLOC_RANGE: - loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord range. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_CREATE_CONTEXT: - loggerProc(LOG_LEVEL_ERROR, "Unable to allocate XRecord context. (%#X)", status); - break; - - case IOHOOK_ERROR_X_RECORD_ENABLE_CONTEXT: - loggerProc(LOG_LEVEL_ERROR, "Failed to enable XRecord context. (%#X)", status); - break; - - - // Windows specific errors. - case IOHOOK_ERROR_SET_WINDOWS_HOOK_EX: - loggerProc(LOG_LEVEL_ERROR, "Failed to register low level windows hook. (%#X)", status); - break; - - - // Darwin specific errors. - case IOHOOK_ERROR_AXAPI_DISABLED: - loggerProc(LOG_LEVEL_ERROR, "Failed to enable access for assistive devices. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_EVENT_PORT: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple event port. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_RUN_LOOP_SOURCE: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop source. (%#X)", status); - break; - - case IOHOOK_ERROR_GET_RUNLOOP: - loggerProc(LOG_LEVEL_ERROR, "Failed to acquire apple run loop. (%#X)", status); - break; - - case IOHOOK_ERROR_CREATE_OBSERVER: - loggerProc(LOG_LEVEL_ERROR, "Failed to create apple run loop observer. (%#X)", status); - break; - - // Default error. - case IOHOOK_FAILURE: - default: - loggerProc(LOG_LEVEL_ERROR, "An unknown hook error occurred. (%#X)", status); - break; - } - - // return status; - // printf("%d\n", status); - return cstatus; -} - int stop_event(){ int status = hook_stop(); switch (status) { diff --git a/extern.go b/extern.go index 631aeb2..77aaace 100644 --- a/extern.go +++ b/extern.go @@ -28,6 +28,7 @@ func go_send(s *C.char) { if err != nil { log.Fatal(err) } + // log.Print("sending stuff") //todo: maybe make non-bloking ev <- out } diff --git a/hook.go b/hook.go index b279a72..6648dd2 100644 --- a/hook.go +++ b/hook.go @@ -77,6 +77,7 @@ var ( keys = map[int][]uint16{} cbs = map[int]func(Event){} events = map[uint8][]int{} + grOn = 0 ) //from robotgo @@ -213,11 +214,15 @@ func Process(EvChan <-chan Event) (out chan bool) { pressed[ev.Keycode] = false } for _, v := range events[ev.Kind] { + if !asyncon { + break + } if allPressed(pressed, keys[v]...) { cbs[v](ev) } } } + // fmt.Println("exiting after end (process)") out <- true }() return out @@ -264,16 +269,32 @@ func KeychartoRawcode(kc string) uint16 { // Adds global event hook to OS // returns event channel func Start() chan Event { - asyncon = true + for grOn != 0 { + // fmt.Println("wating for goroutines to end") + time.After(50 * time.Millisecond) + } ev = make(chan Event, 1024) - go C.startev() + go func() { + grOn += 1 + C.startev() + grOn -= 1 + // fmt.Println("exiting after end (C.startev)") + }() + // fmt.Println("started ev") + asyncon = true + go func() { + grOn += 1 for { - C.pollEv() - time.Sleep(time.Millisecond * 50) - //todo: find smallest time that does not destroy the cpu utilization if !asyncon { + // fmt.Println("exiting after end (start)") + grOn -= 1 return + } else { + // fmt.Println("polling events") + C.pollEv() + time.Sleep(time.Millisecond * 50) + //todo: find smallest time that does not destroy the cpu utilization } } }() @@ -282,13 +303,21 @@ func Start() chan Event { // End removes global event hook func End() { + asyncon = false C.endPoll() C.stop_event() for len(ev) != 0 { <-ev } close(ev) - asyncon = false + pressed = make(map[uint16]bool, 256) + used = []int{} + keys = map[int][]uint16{} + cbs = map[int]func(Event){} + events = map[uint8][]int{} + // for grOn != 0 { + // time.After(time.Millisecond * 50) + // } } // AddEvent add event listener