unosquare/pigpio-dotnet

Passing null to gpioSetAlertFunction crashes the program

mariodivece opened this issue · 2 comments

Stopping alerts makes the program crash (pigpio v67)

  1. Get the sample code and save it to test.cs (code below)
  2. Compile the program mcs test.cs
  3. Run the program and the following output is produced (output below)
  4. Ctrl+C does not work. Nothing else works. I have to start a new shell and kill the process manually.

test.cs

namespace Unosquare.PiGpio.HangExample
{
    using System;
    using System.Runtime.InteropServices;

    class PiGpioTest
    {
        public delegate void PiGpioAlertDelegate(uint userGpio, uint levelChange, uint ticks);

        public static void Main(string[] args)
        {
            // Init the library
            GpioInitialise();

            // Register an alert function
            GpioSetAlertFunc(4, (userGpio, levelChange, ticks) =>
            {
                Console.WriteLine($"GPIO: {userGpio} Level: {levelChange} Ticks: {ticks}");
            });

            // Set an alert watchdog of 1 second
            GpioSetWatchdog(4, 1000);

            // Wait for user input to stop alerts
            Console.ReadKey(intercept: true);
            GpioSetAlertFunc(4, null);
            Console.WriteLine("Correctly stopped alerts.");

            // Wait for the user to end the program gracefully
            Console.ReadKey(intercept: true);
            Console.WriteLine("Program stopped gracefully.");
        }

        [DllImport("libpigpio.so", EntryPoint = "gpioInitialise")]
        public static extern int GpioInitialise();

        [DllImport("libpigpio.so", EntryPoint = "gpioSetAlertFunc")]
        public static extern int GpioSetAlertFunc(uint userGpio, [In, MarshalAs(UnmanagedType.FunctionPtr)] PiGpioAlertDelegate callback);

        [DllImport("libpigpio.so", EntryPoint = "gpioSetWatchdog")]
        public static extern int GpioSetWatchdog(uint userGpio, uint timeoutMilliseconds);
    }
}

output:

pi@raspberrypi:~/pigpio-dotnet $ sudo mono test.exe
GPIO: 4 Level: 2 Ticks: 2063112400
GPIO: 4 Level: 2 Ticks: 2064112652
GPIO: 4 Level: 2 Ticks: 2065112905
GPIO: 4 Level: 2 Ticks: 2066113282
GPIO: 4 Level: 2 Ticks: 2067113535
GPIO: 4 Level: 1 Ticks: 2067530671
GPIO: 4 Level: 2 Ticks: 2068531289
GPIO: 4 Level: 2 Ticks: 2069531916
GPIO: 4 Level: 0 Ticks: 2069980377
GPIO: 4 Level: 1 Ticks: 2070152627
GPIO: 4 Level: 0 Ticks: 2070295198
GPIO: 4 Level: 1 Ticks: 2070470928
GPIO: 4 Level: 0 Ticks: 2070596259
GPIO: 4 Level: 1 Ticks: 2071118840
GPIO: 4 Level: 0 Ticks: 2071373096
GPIO: 4 Level: 1 Ticks: 2071373101
GPIO: 4 Level: 0 Ticks: 2071373131
GPIO: 4 Level: 1 Ticks: 2071811452
GPIO: 4 Level: 0 Ticks: 2072063727
GPIO: 4 Level: 2 Ticks: 2073064425
GPIO: 4 Level: 2 Ticks: 2074064677
GPIO: 4 Level: 2 Ticks: 2075065680
GPIO: 4 Level: 2 Ticks: 2076065682
GPIO: 4 Level: 2 Ticks: 2077066310
Correctly stopped alerts.
Program stopped gracefully.
2018-04-05 08:42:05 sigHandler: Unhandled signal 39, terminating

STATE CUE CARD: (? means a positive number, usually 1 or 2, * means any number)
        0x0     - starting (GOOD, unless the thread is running managed code)
        0x1     - running (BAD, unless it's the gc thread)
        0x2     - detached (GOOD, unless the thread is running managed code)
        0x?03   - async suspended (GOOD)
        0x?04   - self suspended (GOOD)
        0x?05   - async suspend requested (BAD)
        0x?06   - self suspend requested (BAD)
        0x*07   - blocking (GOOD)
        0x?08   - blocking with pending suspend (GOOD)
--thread 0x19eeec0 id 0xb43db470 [(nil)] state 105
--thread 0xb4800480 id 0xb6a57470 [(nil)] state 1
--thread 0x190edd8 id 0xb6f10000 [(nil)] state 1  GC INITIATOR
WAITING for 1 threads, got 0 suspended
suspend_thread suspend took 200 ms, which is more than the allowed 200 ms
2018-04-05 08:42:05 sigHandler: Unhandled signal 6, terminating

I got a response from from @joan2937

Hi Mario,
From the pigpio point of view cancelling alerts with null works fine.
I attach a C test program.
The problem is probably the unhandled signal 39. It's not something I recognise. Any unhandled signal will cause pigpio to terminate as gracefully as possible (to minimise the chance of DMA scribbling over memory).

Is signal 39 generated by .NET/mono?

/* gcc -pthread gpioSetAlertFunc_test.c -lpigpio */
#include <stdio.h>
#include <pigpio.h>
#define PWM 12

void callback(int gpio, int level, uint32_t tick)
{
   printf("GPIO %d became %d at %d\n", gpio, level, tick);
}

int main(int argc, char *argv[])
{
   int i;

   if (gpioInitialise() < 0) return -1;
   gpioHardwarePWM(PWM, 5, 500000); /* 5 Hz square wave */

   for (i=0; i<10; i++)
   {
      // call callback whenever GPIO changes state
      printf("callbacks on\n");
      gpioSetAlertFunc(PWM, callback);
      time_sleep(2);
      // cancel callback
      printf("callbacks off\n");
      gpioSetAlertFunc(PWM, NULL);
      time_sleep(2);
   }   

   gpioHardwarePWM(PWM, 0, 0);
   gpioTerminate();
   return 0;
}
stale commented

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.