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 <stdlib.h>
|
||||||
#include "pub.h"
|
#include "pub.h"
|
||||||
#include "../chan/eb_chan.h"
|
#include "../chan/eb_chan.h"
|
||||||
|
|
||||||
|
void dispatch_proc(iohook_event * const event);
|
||||||
|
|
||||||
eb_chan events;
|
eb_chan events;
|
||||||
|
|
||||||
void go_send(char*);
|
void go_send(char*);
|
||||||
@ -24,10 +27,15 @@ void go_sleep(void);
|
|||||||
bool sending = false;
|
bool sending = false;
|
||||||
|
|
||||||
void startev(){
|
void startev(){
|
||||||
|
// puts("start_ev");
|
||||||
events = eb_chan_create(1024);
|
events = eb_chan_create(1024);
|
||||||
eb_chan_retain(events);
|
eb_chan_retain(events);
|
||||||
sending = true;
|
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(){
|
void pollEv(){
|
||||||
@ -116,89 +124,6 @@ void dispatch_proc(iohook_event * const event) {
|
|||||||
// fprintf(stdout, "----%s\n", buffer);
|
// 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 stop_event(){
|
||||||
int status = hook_stop();
|
int status = hook_stop();
|
||||||
switch (status) {
|
switch (status) {
|
||||||
|
@ -28,6 +28,7 @@ func go_send(s *C.char) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
// log.Print("sending stuff")
|
||||||
//todo: maybe make non-bloking
|
//todo: maybe make non-bloking
|
||||||
ev <- out
|
ev <- out
|
||||||
}
|
}
|
||||||
|
41
hook.go
41
hook.go
@ -77,6 +77,7 @@ var (
|
|||||||
keys = map[int][]uint16{}
|
keys = map[int][]uint16{}
|
||||||
cbs = map[int]func(Event){}
|
cbs = map[int]func(Event){}
|
||||||
events = map[uint8][]int{}
|
events = map[uint8][]int{}
|
||||||
|
grOn = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
//from robotgo
|
//from robotgo
|
||||||
@ -213,11 +214,15 @@ func Process(EvChan <-chan Event) (out chan bool) {
|
|||||||
pressed[ev.Keycode] = false
|
pressed[ev.Keycode] = false
|
||||||
}
|
}
|
||||||
for _, v := range events[ev.Kind] {
|
for _, v := range events[ev.Kind] {
|
||||||
|
if !asyncon {
|
||||||
|
break
|
||||||
|
}
|
||||||
if allPressed(pressed, keys[v]...) {
|
if allPressed(pressed, keys[v]...) {
|
||||||
cbs[v](ev)
|
cbs[v](ev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fmt.Println("exiting after end (process)")
|
||||||
out <- true
|
out <- true
|
||||||
}()
|
}()
|
||||||
return out
|
return out
|
||||||
@ -264,16 +269,32 @@ func KeychartoRawcode(kc string) uint16 {
|
|||||||
// Adds global event hook to OS
|
// Adds global event hook to OS
|
||||||
// returns event channel
|
// returns event channel
|
||||||
func Start() chan Event {
|
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)
|
ev = make(chan Event, 1024)
|
||||||
go C.startev()
|
|
||||||
go func() {
|
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 {
|
for {
|
||||||
C.pollEv()
|
|
||||||
time.Sleep(time.Millisecond * 50)
|
|
||||||
//todo: find smallest time that does not destroy the cpu utilization
|
|
||||||
if !asyncon {
|
if !asyncon {
|
||||||
|
// fmt.Println("exiting after end (start)")
|
||||||
|
grOn -= 1
|
||||||
return
|
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
|
// End removes global event hook
|
||||||
func End() {
|
func End() {
|
||||||
|
asyncon = false
|
||||||
C.endPoll()
|
C.endPoll()
|
||||||
C.stop_event()
|
C.stop_event()
|
||||||
for len(ev) != 0 {
|
for len(ev) != 0 {
|
||||||
<-ev
|
<-ev
|
||||||
}
|
}
|
||||||
close(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
|
// AddEvent add event listener
|
||||||
|
Loading…
x
Reference in New Issue
Block a user