0

So I have the following, working, code for getting clean exit performed when user interrupts the program (ie. ctrl-c in terminal), so that global destructors, etc. will be run. The problem is that it is very limited what you can do in the signal handler function (it did take me a little while to figure out how to this correctly (as simpel as it looks now) - the trick is starting a thread to moniter a flag - but now im left wondering if theres a better way to avoid burning cpu ? (in particular now as i plan to include this with some library code)

      std::signal(SIGINT, [](int signal) { gSignalStatus() = signal; });
     
      std::thread signal_handler_thread([] {
          using namespace std::chrono_literals;
          for (;;)
          {
              if (gSignalStatus() != 0)
              {
                  std::exit(gSignalStatus());
              }
              std::this_thread::sleep_for(100ms);
          }
      });
      signal_handler_thread.detach();

Sleeping is a very very crude solution - but is there any better way (for example wake up the thread from the signal handler, but we are not allowed to that...) ?

darune
  • 10,480
  • 2
  • 24
  • 62
  • Please don't tag with every version of C++ under the sun, tag with the version *you're using*. – tadman Jan 23 '21 at 17:18
  • Instead of having a thread grinding its gears waiting for a signal, why not create that thread when the condition is triggered? You could also use a [condition variable](https://en.cppreference.com/w/cpp/thread/condition_variable) to trigger the exit behaviour. – tadman Jan 23 '21 at 17:20
  • It is certainly not a good idea to just call `std::exit` from an arbitrary thread all of it sudden, or detach a thread. You should rework all your signal handling. – user7860670 Jan 23 '21 at 17:24
  • What you're really trying to do is implement signal handling in your main execution thread (or some `std::thread`). This is outside the scope of the C++ standard but there are often operating system-specific ways to do that. Unfortunately you have not indicated whether or not you're looking for an operating system-specific solution. – Sam Varshavchik Jan 23 '21 at 17:34
  • 1
    Here's a hint: If your sleep was 1ms instead of 100ms, you would probably not feel the need to ask the question :) – Michaël Roy Jan 23 '21 at 17:36
  • @user7860670 if not provided the process will exit without cleanup in my case leaving the terminal in a messed up state. – darune Jan 23 '21 at 18:24
  • @MichaëlRoy I think 100ms is not an issue usually since you can hardly feel that when pressing "ctrl-c" - but i think i will just go with sleep, its just that sleep is usually an anti-pattern – darune Jan 23 '21 at 18:26
  • If the aim is simply a clean exit after receiving a signal then why not have the signal handler write to one end of a [pipe](https://man7.org/linux/man-pages/man2/pipe.2.html)? The main thread (or some other 'monitor' thread) can be blocked on a read to the pipe ([select](https://man7.org/linux/man-pages/man2/select.2.html), [poll](https://man7.org/linux/man-pages/man2/poll.2.html) or whatever) and, when the read succeeds, perform whatever functionality is necessary within the main application/non-interrupt context. – G.M. Jan 23 '21 at 19:51
  • @G.M. i dont think you allowed to that in the signal_handler – darune Jan 24 '21 at 21:31
  • cf.[this link](https://man7.org/linux/man-pages/man7/signal-safety.7.html). Not sure if it's definitive but... – G.M. Jan 24 '21 at 21:50
  • Sorry, my previous comment was a bit 'terse' to say the least. In essence, though, as far as POSIX is concerned I think it's okay for an ISR and a user space routine to communicate using a previously configured `pipe` using [`read`](https://man7.org/linux/man-pages/man2/read.2.html) and [`write`](https://man7.org/linux/man-pages/man2/write.2.html). – G.M. Jan 24 '21 at 22:10
  • @G.M. is right - you should have [a signal handling thread that then uses some other mechanic](https://stackoverflow.com/a/2700597/132382) to propagate the signal to your shutdown thread. You can do several things inside of a signal handler [safely](https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03), such as writing to a pipe. – pilcrow Jan 24 '21 at 22:11
  • @G.M. but is that also then allowed with c++ standard ? this is crossplatform, not even 100% that posix is fully there. – darune Jan 25 '21 at 08:47
  • Okay, I'd assumed (perhaps rather optimistically) that a certain level of POSIX compliance could be relied upon. If that's not the case then my suggestion is obviously somewhat moot. Having said that, I don't recall working on a system -- desktop, embedded or otherwise -- where signals were implemented but there *wasn't* a guaranteed level of POSIX compatibility. – G.M. Jan 25 '21 at 13:44
  • @G.M. Keep in mind I am not interested in manual cross compilation to a host of different platforms/compilers. Much more simpel to stay within standard, don't you think ? – darune Jan 28 '21 at 21:27

0 Answers0