0

I'm sending a signal.CTRL_BREAK_EVENT to a QApplication subprocess and the subprocess's handler manages to catch the signal (and perform some magic before exiting). However, when the signal is sent, it is not processed until I interact with the QApplication window (causing it to somehow use CPU cycles LOL), only then will it handle the signal.

E.g.

  1. I start QApplication as subprocess
  2. I send a signal.CTRL_BREAK_EVENT (from server that started the subprocess).
  3. Nothing happens.
  4. I click on any button in the QApplication.
  5. It handles the signal.CTRL_BREAK_EVENT and exits.

I would of course prefer step 5 to take place at step 3.

What's wrong? How would I "refresh" the QApplication or virtualy click a button when it's run in a subprocess? I suspect that the QApplication's main event loop somehow is in idle mode... until the application is interacted with. (?)

server.py

app = None

def start_app():
    global app

    app = subprocess.Popen("python app.py")

def exit_app():
    global app

    p = app.poll()
    if p==None:
        print("Subprocess is alive") # debug
    app.send_signal(signal.CTRL_BREAK_EVENT)

app.py

import sys, signal
from runner import mainWindow

from PyQt5.QtWidgets import QApplication

app = None
mw = None

def exit_signal_handler(signal, frame):
    global app, mw

    print("Terminate signal received")
    app.quit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    signal.signal(signal.SIGBREAK, exit_signal_handler)

    mw = mainWindow.MainWindow() # this is the Qt window starting
    mw.actionExit.triggered.connect(app.quit)

    sys.exit("Runner exit with code: " + str(app.exec()))
niCk cAMel
  • 869
  • 1
  • 10
  • 26
  • Can you show how you `connect()` the signal .. and where? – Mohammad Kanan Feb 08 '18 at 17:47
  • @MohammadKanan It's described in detail here : https://stackoverflow.com/q/47306805/2923755. If you see something important there I can edit the question – niCk cAMel Feb 08 '18 at 18:07
  • Not much familiar with Py. my understanding however is that when you start Qapp subprocess it would start its (blocking) event loop (?) So your signal is being blocked, what I can't understand is why pressing arbitrary button exits or deblocks that event loop! – Mohammad Kanan Feb 08 '18 at 18:17
  • I asked where you are connecting your Signal/Slot because it could be related, if the connect() is done inside the Qapp sub process then its supposed to work – Mohammad Kanan Feb 08 '18 at 18:18
  • @MohammadKanan Ok so, there's no `connect()` involved here, the signal is caught by `exit_signal_handler(signal, frame)` in app.py in the link I provided – niCk cAMel Feb 08 '18 at 18:31
  • http://idownvotedbecau.se/nocode/, http://idownvotedbecau.se/nomcve/, http://idownvotedbecau.se/nodebugging/ – Murphy Feb 08 '18 at 22:47
  • 1
    @Murphy clever. [ihaveaddedco.de/sohelp](https://stackoverflow.com/help/how-to-answer) – niCk cAMel Feb 08 '18 at 23:45
  • 2
    I do not know if your example has trimmed several things but I notice that app is a local variable in server.py, your example is not a [mcve], it can not be verified since it is imcomplete – eyllanesc Feb 09 '18 at 00:19
  • @eyllanesc . Yes, highly trimmed. I've edited now to include more code – niCk cAMel Feb 09 '18 at 10:47
  • This is still not a [mcve]. `server.py` does nothing when started on my system (of course, any start code is missing), and `app.py` is missing the `runner` module. – Murphy Feb 09 '18 at 16:27
  • @Murphy I see your point, but if one is to throw a downvote because not all rules are **literally** met, then you'd have to downvote the majority of questions on SO. That's not to justify my "mistake", it's just a fact. Furthermore, since I suspect something is going on in the QApplication's main event loop, which is somehow paused and only resumed upon interaction, I figure someone with enough knowledge will spot the issue without having to have access to all the code in question – niCk cAMel Feb 09 '18 at 17:20
  • You haven't read the provided links, have you? You're wasting people's time. – Murphy Feb 09 '18 at 17:26
  • @Murphy and you didn't read what I said. You know, you're not obliged to revisit and comment. You've thrown your downvote, provided links.. I mean you're done. Thank you for the effort but do not revisit. – niCk cAMel Feb 09 '18 at 17:33
  • could the QApp run within a thread? I *guess* it blocked on a sys call and signal in windows can not break blocking sys call. – georgexsh Feb 11 '18 at 03:33

1 Answers1

0

Adding a Qtimer() in app.py for poll reasons seems to do the trick. Any signals sent will be processed every second when pollMe()is called by Qtimer

import sys, signal
from runner import mainWindow
from PyQt5 import QtCore           #<---- NEW
from PyQt5.QtWidgets import QApplication

app = None
mw = None

def pollMe():                      # <--- NEW
    timerPoll.start(1000)

def exit_signal_handler(signal, frame):
    global app, mw

    print("Terminate signal received")
    app.quit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    signal.signal(signal.SIGBREAK, exit_signal_handler)

    timerPoll = QtCore.QTimer()        #<---- NEW
    timerPoll.timeout.connect(pollMe)
    timerPoll.start(1000)

    mw = mainWindow.MainWindow() # this is the Qt window starting
    mw.actionExit.triggered.connect(app.quit)

    sys.exit("Runner exit with code: " + str(app.exec()))
niCk cAMel
  • 869
  • 1
  • 10
  • 26