1

Basically forking means to make an exact copy of the current process into another process upto the point of forking (right? It's the way I've understood, please correct me if I'm wrong)

So, In a GUI if I put a code to a say button that forks a process to open a browser, shouldn't that make my current GUI window into two GUI windows? But the result is only one. What I mean by making two GUI windows is that, if it copies the process up to the point of forking then Shouldn't it also make a duplicate window since it copied all the code?

The minimal runnable code is here:

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
import webbrowser, os

class something(BoxLayout):
    def __init__(self):
        super().__init__()
        self.add_widget(Button(text='test button'))
        self.add_widget(Label(text='[ref=video]google.com[/ref]',
                    markup=True,
                    on_ref_press=lambda *_: self.open_browser('https://google.com')))

    def open_browser(self, site):

        if not os.fork():
            webbrowser.open(site)






class MainApp(App):
    def build(self):
        return something()


if __name__ == '__main__':
    MainApp().run()  

For some reason the GUI becomes unresponsive after it does the fork and there are no two GUI windows after the forking is done. What is the theory behind it?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
juztcode
  • 1,196
  • 2
  • 21
  • 46
  • 2
    a fork does not copy the process, it just creates another process. – eyllanesc May 01 '18 at 17:22
  • Possible duplicate of [Python:How os.fork() works?](https://stackoverflow.com/questions/33560802/pythonhow-os-fork-works) – eyllanesc May 01 '18 at 17:30
  • 1
    @eyllanesc , then why does the GUI become unresponsive? – juztcode May 02 '18 at 01:52
  • because webbrowser is blocking. – eyllanesc May 02 '18 at 01:56
  • @eyllanesc , and how can it block when it's forked on a separate process? – juztcode May 02 '18 at 02:01
  • 1
    What do you think happens with the parent process when a fork is made? Why do not you use a thread? – eyllanesc May 02 '18 at 02:02
  • 1
    `os.fork()` does make a copy of the process. In the parent process, the call returns the process id of the child. In the child process (which is a copy of the parent), the call returns 0. I suspect that calling `os.fork()` in a Kivy App is likely to cause problems. In your case, I don't think you even need to fork, A simple call to `webbrowser.open()` will start the web browser in its own window and your Kivy App will continue. – John Anderson May 02 '18 at 02:05
  • @JohnAnderson , yes that's true , but I want to know why? As you have pointed out it _makes_ a copy of the process, so why isn't there another GUI window popping up? And is the web browser internally threaded or something(need to know why it just works to prepare for later possibilities).I didn't find information if it's threaded in the docs. – juztcode May 02 '18 at 02:23
  • @eyllanesc , please see John Anderson 's comment above – juztcode May 02 '18 at 02:26
  • 2
    The fork makes a copy of the process, but doesn't re-run your gui building code (the stuff in something.__init__()), so you get two processes, both of which think they are a Kivy App with the same GUI. I am guessing that some of the references to the GUI in the child process will be invalid. – John Anderson May 02 '18 at 02:42
  • 1
    Also, the `webbrowser.open()` starts another process using `subprocess.popen()` to run the browser. – John Anderson May 02 '18 at 02:51
  • @JohnAnderson , even if the references in the child process could be invalid, why does it effect the main GUI at all? They're two completely independent processes right? – juztcode May 02 '18 at 02:53
  • 1
    When I run your code (I am using Ubuntu), the GUI continues to run, though it appears to hang for a short period. I added a method to print the pid to your `test button`, and after using the `google.com` button, I have to click the 'test button` several time before it works. I also get an error from `xcb` that I believe is the child process dying. Don't know why the parent process seems to get stuck temporarily. – John Anderson May 02 '18 at 03:08
  • 1
    Actually, I only get the temporary hang when I run your code from PyCharm. – John Anderson May 02 '18 at 03:14
  • 1
    I am running Kivy v1.10.0 and Python v3.6.1, are you running the same? – John Anderson May 02 '18 at 03:16
  • 1
    @JohnAnderson, yes I'm running the same version, but this is a bit of minimal code I've presented, I've got this text on a label with several nested widgets and It gives me a traceback saying Abort core dumped. [Here is the traceback](https://pastebin.com/RV25PnGy) and [Here is the actual class implemented in](https://pastebin.com/fmguJzTD) – juztcode May 02 '18 at 03:33
  • 1
    Yes, that is the same error that I see. So I think the conclusion is that you cannot do `os.fork()` in a Kivy App. If you need a separate process, use the `multiprocessing` package. If you need a second GUI, you can either do an `os.fork()` before calling `MainApp().run()` or start a subprocess that runs another instance of your App. In either of those two cases, you will end up with two independent instances of your running App. – John Anderson May 02 '18 at 13:47

0 Answers0