Giter Site home page Giter Site logo

Comments (10)

nwhetsell avatar nwhetsell commented on June 18, 2024

This may be an issue with the Csound API. I was able to reproduce this outside of Node.js, and I’ve opened an issue at csound/csound#778.

from csound-api.

nwhetsell avatar nwhetsell commented on June 18, 2024

So, using the Csound API sets, by default, a signal handler that can delay or prevent termination of a process, almost always (but not necessarily, it seems) when running Csound on a background thread.

The simplest solution I can think of is to just not use the Csound API signal handler. I can do this by putting

csoundInitialize(CSOUNDINIT_NO_SIGNAL_HANDLER);

at the beginning of the binding to csoundCreate. This would mean that, by default, the Csound API signal handler would not be set, and pressing Ctrl-C would terminate Node.js as expected. If someone wants to use the Csound API’s default signal handler for some reason, you’d just need to run

csound.Initialize();

(with no arguments) before any calls to csound.Create(). Some remarks about the drawbacks of doing this are at csound/csound#778 (comment).

From there, I think potential solutions get complex pretty quickly. At minimum, I think I’d need

  • A custom signal handler that sets a global “stop everything now” flag
  • An extra check for this flag in the csoundPerformKsmps loops here and here
  • Some kind of mechanism (maybe a global list of performing Csound instances that gets removed from in HandleOKCallback and WorkComplete) that actually enforces finishing and cleaning up after Csound performances before re-raising the signal

My leaning, of course, is to not use the Csound API signal handler. What do you think?

from csound-api.

aliask avatar aliask commented on June 18, 2024

I must admit I didn't expect the answer to be so complicated!

I have done a bit of reading on signals in multithreaded applications this morning and from what I can tell the standard approach appears to be setting up a single handler which takes care of signals for everything. As the API caller (csound-api in this case) is the one setting up the threads, I suppose it falls on us to handle the interrupts. So this would mean CSOUNDINIT_NO_SIGNAL_HANDLER and creating our own handler function.

What is the advantage of having a global flag (needing the dot points above) versus just calling csound.Stop()/csound.Destroy()?

from csound-api.

nwhetsell avatar nwhetsell commented on June 18, 2024

I’m honestly not sure about this myself, but here goes…

If you mean calling csound.Stop and csound.Destroy in JavaScript in response to signals, it’s a possibility, but I think this would mean that every csound-api user would then have to handle signals in JavaScript; anyone running Csound asynchronously in Node.js would need to use process.on. Ideally, though, I’d like csound-api to “just work” and handle signals for you (if you want it to).

If you mean calling the csoundStop and csoundDestroy C API functions in a signal handler, this gets tricky, I’m afraid. The asynchronous Csound performance functions of csound-api (PerformAsync and PerformKsmpsAsync) both use csoundPerformKsmps (the C function) under the hood. This is because, despite being nominally thread-safe, functions like csoundInputMessage must be called on Csound’s performance thread to avoid unacceptable delays on everything other than macOS (which I found out with issue #7). So, if you call csound.PerformAsync in Node.js, and then use csound.InputMessage, you’re really setting up a loop that calls csoundPerformKsmps repeatedly and gets input arguments for csoundInputMessage (and a few other functions) off of a queue. This is happening here and here.

The upshot is that there needs to be a way to break out of these csoundPerformKsmps loops in response to a signal, and csoundStop doesn’t do that. About the only thing I can think of to do (and what seems to be suggested here) is set a flag that can be checked in these loops.

The idea behind the last bullet point is that if there are asynchronous Csound performances in progress when a SIGINT occurs, we still need to re-raise the signal, call the default signal handler, or otherwise do something to terminate Node.js. When should we do this? Most likely when all the csoundPerformKsmps loops are broken out of. Either HandleOKCallback or WorkComplete are called when that happens. So, if the “a signal was raised so stop everything” flag was set, HandleOKCallback or WorkComplete would need to somehow terminate Node.js when the last asynchronous Csound performance ends.

from csound-api.

aliask avatar aliask commented on June 18, 2024

this would mean that every csound-api user would then have to handle signals in JavaScript

I see. I thought that it might be possible within the library, but if that's not the case it's definitely not a "just works" solution and the flag option is the way.

So it sounds like the solution would be to catch the signal, terminate all playing instruments (via flag on csoundPerformKsmps loop), then re-raise the signal on the main thread.

from csound-api.

nwhetsell avatar nwhetsell commented on June 18, 2024

I pushed a possible fix for this in commit a54e6c3. Can you take a look and give it a spin?

from csound-api.

aliask avatar aliask commented on June 18, 2024

The code makes sense to me, and from my tests everything is working as expected. I've tested with single performers and many, both situations work fine.

Are there any other signals we should catch other than SIGINT and SIGTERM?

from csound-api.

nwhetsell avatar nwhetsell commented on June 18, 2024

Maybe. The Csound API signal handler ignores SIGPIPE, sets a flag on SIGINT and SIGTERM, and exits on everything else. I’m not sure how handling more signals would interact with Node.js, though; my leaning is to stick with just SIGINT and SIGTERM, for now.

from csound-api.

aliask avatar aliask commented on June 18, 2024

I just tested with a bunch of other ones and they all exit fine anyway.

from csound-api.

nwhetsell avatar nwhetsell commented on June 18, 2024

Awesome, thanks!

from csound-api.

Related Issues (17)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.