mirror of
https://github.com/robotn/gohook.git
synced 2025-04-28 02:04:59 +08:00
fixed segfault when starting and stoping the event hook too quickly, it was a data race
This commit is contained in:
parent
e047a93060
commit
6c9e89be03
@ -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) {
|
||||
|
@ -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
41
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user