Handling SIGINT in Kotlin Native
Tags: kotlin, c, cpp
Published: 2020-01-15 09:11:03

Just 2 weeks ago Patrick Lemke on the Kotlin Slack in the #kotlin-native channel asked an [interesting question](https://kotlinlang.slack.com/archives/C3SGXARS6/p1577698245105700):

![Original question by Patrick Lemke: How do I react to a SIGINT event in Kotlin Native?](https://thepracticaldev.s3.amazonaws.com/i/26p3133suflzbkh9y02u.png)

I was intrigued by this question. A SIGINT is the event sent to a process if you press `Ctrl + C` in the shell, and that usually exits a process. So how would you actually handle events like SIGINT in Kotlin Native? 🤔

At first I thought this would be hard to implement. I tried to create a small example. On my way I not only managed to implement this, but discovered how Kotlin tooling and documentation can help you in solving similar problems. Onward!

## How C/C++ handle SIGINT

At first it's probably a good idea to read about how these interrupts are actually created in C/C++. I searched for 'handle sigint c/c++' on Google and found a page on [C++ Signal Handling](https://www.tutorialspoint.com/cplusplus/cpp_signal_handling.htm). Basically, you define a function in C++ and you can register it as a signal handler by calling the `signal` function (that's the only C++ code I'll show here):

```cpp
void signalHandler(int signum) {
    // your logic here when interrupt happens
}

int main () {
    // register your handler function - can be SIGINT, SIGABRT, or others
    signal(SIGINT, signalHandler);

    // ever-running code here that can/will be interrupted
}
```

## Calling `signal` in Kotlin Native

Now let's find out how we can call that function in Kotlin Native! First, I opened IntelliJ, and created a new Kotlin Native project with `Create New Project -> Kotlin -> Native | Gradle`. This automatically creates a sample main file. Let's see if it can find a `signal` function. And jackpot - there it is, and it can be imported!

![signal function from platform.posix in IntelliJ](https://thepracticaldev.s3.amazonaws.com/i/r6r4sazcpe1iu6ymook5.png)

And SIGINT and the other constants can be found as well:

![SIGINT, SIGTERM, and more](https://thepracticaldev.s3.amazonaws.com/i/xxrirdulkg7d8olxjq02.png)

I think this is tooling by IntelliJ/Kotlin is pretty amazing. It looks simple, but there is actually a whole lot going on under the covers. The POSIX bindings are created automatically for you and the platform(s) you target, and they are already indexed, waiting for you to type-and-complete.

Now, moving to the second parameter: we already know this is a lambda. But what the heck is a `CPointer<CFunction<(Int) → Unit>>?` - and how do I get one? I had no idea, because I've never done this before in Kotlin (although I know what a pointer is). So I googled for 'kotlin cpointer cfunction', and landed on this excellent Kotlin documentation: [Mapping Function Pointers from C
](https://kotlinlang.org/docs/tutorials/native/mapping-function-pointers-from-c.htm)

And there it is - scrolling down I find exactly what I need: [Passing Kotlin Function as C Function Pointer](https://kotlinlang.org/docs/tutorials/native/mapping-function-pointers-from-c.html#passing-kotlin-function-as-c-function-pointer) Using that, we now know that Kotlin provides a helper function called `staticCFunction`. Let's use that!

So a trivial example might be that we print something forever. And then we will interrupt it. Here's my first, trivial implementation:

```kotlin
fun main() {
    signal(SIGINT, staticCFunction<Int, Unit> {
        println("Interrupt: $it")
    })
    while (true) {
        println("running")
        sleep(1)
    }
}
```

When we compile this (by clicking the `Build` button), it will create a binary with the name of our project and a `.kexe` ending. For me, it created a file under `build/bin/macos/debugExecutable/kotlin-native-signal.kexe`. I wanted to call the main method directly via the common 'green arrow run button', but that wasn't there. For now, we'll use the commandline - but I hope JetBrains continues to improve the tooling around Kotlin Native (see that section further down).

So let's call the program in a shell, and press `Ctrl + C` after 2 seconds to interrupt it:

```console
$ build/bin/macos/debugExecutable/kotlin-native-signal.kexe
running
running
^CInterrupt: 2
running
running
running
[program continues, does not exit]
```

Nice, it does handle the interrupt! 🙂

But we didn't actually exit the program in our interrupt handler - so now the program will continue forever. Unless we kill it with `killall`… 😈

```plain
# in a second shell:
$ killall kotlin-native-signal.kexe

# in the first shell this will kill the program:
[1]    66077 terminated  build/bin/macos/debugExecutable/kotlin-native-signal.kexe
```

To improve this program, we can call the (POSIX function!) `exit` in the interrupt. Also, we can use `staticCFunction` to create a CPointer reference to an existing Kotlin function as well. Here's the improved version, with imports added for reference:

```kotlin
import kotlinx.cinterop.staticCFunction
import platform.posix.SIGINT
import platform.posix.exit
import platform.posix.signal
import platform.posix.sleep

fun handleSignal(signalNumber: Int) {
    println("Interrupt: $signalNumber")
    exit(0)
}

fun main() {
    signal(SIGINT, staticCFunction(::handleSignal))
    while (true) {
        println("running")
        sleep(1)
    }
}
```

Finally, when we interrupt the program with `Ctrl + C`, it will run our handler code and exit.

## IntelliJ: A tooling improvement suggestion

When I wrote this blogpost I wanted to run the `main` method directly from the editor. But where usually I expect to find a green run icon of happiness there was just an empty grey area:

![Missing run icon in IntelliJ Community edition](https://thepracticaldev.s3.amazonaws.com/i/490aes88vvzv04exuazq.png)

At first I tried the free community edition of IntelliJ. Next, I tried IntelliJ Ultimate. I opened the same project. Ultimate suggested I install a plugin, so I did that:

![IntelliJ Ultimate: Plugin for Kotlin Native](https://thepracticaldev.s3.amazonaws.com/i/hi3yeyclfiuor1q3lujc.png)

Nevertheless: even after doing that and restarting the IDE, Ultimate didn't show me the green run button. In the 'Run Configurations', I got a new entry 'Kotlin/Native Application' - but it didn't detect my Kotlin Native executable, so I couldn't select that.

Finally, I tried CLion. I installed an additional plugin for Kotlin Native. Still, no run icon to the left of the `main` method. But at least I got a run configuration that way, and I could run & debug the Kotlin Native program from the IDE! 🎉

![CLion: debug a Kotlin Native program](https://thepracticaldev.s3.amazonaws.com/i/2tcf4t9e57h5lyomz768.png)

So for tooling, I have the following wishes:

- I'd love to have that green run icon. It's there in C/C++ programs in CLion and in all Java projects, so why not here?
- IntelliJ Community could make the suggestion that run/debug is only supported in the commercial tools.
- IntelliJ Ultimate and CLion should behave consistently. What works in CLion should work in Ultimate as well.

## Conclusion

This was a fun ride! It's so amazing that we can use POSIX APIs and more (iOS & MacOS libs, etc.) in Kotlin Native - and the coding tooling is great already. There are still some things that could be improved. Then again, Kotlin Native is still a relatively new technology. But it's already on a good way to becoming stable!

If you liked this post, please give it a ❤️ and follow me on [Twitter](https://twitter.com/mreichelt)!