Ziv Ofir
Ziv Ofir

Reputation: 103

Function does not work when started by multiprocess

I have a C function allocates an integer, passes the pointer to a callback function before returning the pointer.

void change_state(int gpio, int level, uint32_t tick, void *ptr){
    if (level == 1){
        printf("Button was pressed!\n");
        *((int*)ptr) += 1;
    }
}

int * allocate_void_ptr_start_watchdog(int BUTTON){
    void *current_state_ptr = malloc(sizeof(int)); /*Creates a ptr of size int*/
    *((int*)current_state_ptr) = 0; /*Casts ptr to type int and set to 0*/
    gpioSetAlertFuncEx(BUTTON, change_state, current_state_ptr); /*Function to watch for GPIO state change*/
    return current_state_ptr; 
}

The return value is then passed back to Python:

allocate_ptr_start_watchdog = button_functions.allocate_void_ptr_start_watchdog
allocate_ptr_start_watchdog.restype = ctypes.POINTER(ctypes.c_int)
ptr = allocate_ptr_start_watchdog(BUTTON)

Using a while True loop as follows works as expected (1 press of button at GPIO 25 will turn lights on, second press turns it off)

while True:
    current_val = ptr.contents.value
    if current_val == 0:
        continue
    elif current_val == 1:
        button_functions.turn_on_lights(LED_1, LED_2)
    else:
        button_functions.clear_all(LED_1, LED_2)
        ptr.contents.value = 0

However once I try to use multiprocessing the function breaks as the button presses don't turn on or off the lights anymore. However, the printf from the C library still prints so I doubt it's an issue with the library.

def button_start(ptr):
    while True:
        current_val = ptr.contents.value
        if current_val == 0:
            continue
        elif current_val == 1:
            button_functions.turn_on_lights(LED_1, LED_2)
        else:
            button_functions.clear_all(LED_1, LED_2)
            ptr.contents.value = 0


multiprocessing.Process(target=button_start, args=(ptr,)).start()

This is running on Raspbian Buster with kernel 5.10.63-v7l+. What am I missing/failing to see here?

Upvotes: 2

Views: 88

Answers (1)

Ziv Ofir
Ziv Ofir

Reputation: 103

As the MP process needs to connect back to the pigpio daemon there needs to be a function that performs that.

int connect_to_daemon(){ /*Connect to pigpio daemon*/
    printf("Connecting to daemon\n");
    int daemon_instance = pigpio_start("192.168.86.234", NULL);
    printf("Successfully connected to daemon\n");
    return daemon_instance;
}

We can then assign a variable to this instance in Python daemon_instance = button_function.connect_to_daemon() before calling our callback function.

int * start_callback(int daemon_instance, int BUTTON){
    void *current_state_ptr = malloc(sizeof(int)); /*Creates a ptr of size int*/
    *((int*)current_state_ptr) = 0; /*Casts ptr to type int and set to 0*/
    callback_ex(daemon_instance, BUTTON, FALLING_EDGE, change_state, current_state_ptr);
    return current_state_ptr;
}

In Python:

ptr = button_functions.start_callback(daemon_instance, BUTTON)
print(ptr.contents.value)  # This should return the correct value now

Big thanks to 2e0byo!

Upvotes: 1

Related Questions