fixed segfault when starting and stoping the event hook too quickly, it was a data race

This commit is contained in:
caue 2020-03-30 02:24:38 -03:00
parent e047a93060
commit 6c9e89be03
3 changed files with 45 additions and 90 deletions

View File

@ -16,6 +16,9 @@
#include <stdlib.h>
#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) {

View File

@ -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
}

41
hook.go
View File

@ -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