Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent creating new console on Windows #346

Merged
merged 1 commit into from Apr 12, 2018

Conversation

@nanoant
Copy link
Contributor

nanoant commented Jan 30, 2018

When running Jupyter via pythonw e.g. pythonw -m qtconsole, jupyter_client launches new kernel via python.exe which is a console application on Windows - a side-effect of that is a new empty console window created and shown as long as kernel is running.

This patch adds CREATE_NO_WINDOW 0x08000000 to Windows specific creationflags. This flag is not exported by subprocess module therefore has to be provides numerically.

Read more, e.g.:
https://stackoverflow.com/questions/2935704/running-shell-commands-without-a-shell-window

@takluyver

This comment has been minimized.

Copy link
Member

takluyver commented Feb 6, 2018

Thanks! I've got a couple of concerns about doing this:

  1. If you're running the Jupyter application from a console window, does passing CREATE_NO_WINDOW mean the kernel process can't print logging to the console? That logging can be pretty useful in some situations.
  2. We've had some issues with pythonw where a process trying to write to stdout/stderr fills up a buffer that nothing is reading from, and then hangs. We have some code to detect pythonw and specifically work around this. Is using python with CREATE_NO_WINDOW going to lead to the same issue because nothing is reading stdout/stderr?
@nanoant

This comment has been minimized.

Copy link
Contributor Author

nanoant commented Feb 13, 2018

@takluyver No, this flags just prevents creating console window if the parent process is GUI app (has no own console handle), but the stdin/out functionality should not be affected.

Just to make sure, I have created simple proof-of-concept script that shows that CREATE_NO_WINDOW does no break Popen:

def test():
    import subprocess
    with subprocess.Popen(['cmd', '/c', 'dir'],
                          creationflags=0x08000000,  # CREATE_NO_WINDOW
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE,
                          shell=False) as p:
        out = p.stdout.read()
    return out.decode('utf-8')

if __name__ == '__main__':
    import ctypes
    MessageBox = ctypes.windll.user32.MessageBoxW
    MessageBox(None, test(), 'cmd', 0)

Now when I run it via pythonw (no console - GUI app) there's no extra console window, but if I comment out creationflags line and run pythonw there's cmd popup shown for a fraction of second.

In case when the script is run via python then it does not matter since the python is console app, just before MessageBox is shown.

P.S. This all is caused by Windows weird separation for console vs GUI apps, that simply does not exist in UNIX world, and I wouldn't care, but I recently have to work on Windows workstation :).

@nanoant

This comment has been minimized.

Copy link
Contributor Author

nanoant commented Apr 12, 2018

@takluyver Hello, Is there anything else I can do to get this checked in?

@takluyver takluyver added this to the 5.3 milestone Apr 12, 2018
@takluyver

This comment has been minimized.

Copy link
Member

takluyver commented Apr 12, 2018

Oh sorry, it had just dropped off my radar.

Can you confirm that if you use this option from a process running in a console, without piping stdout/stderr, the child process can still write to the console that it's in?

If this causes problems for Windows users when we release it, I might ping you to ask about it.

@nanoant

This comment has been minimized.

Copy link
Contributor Author

nanoant commented Apr 12, 2018

Can you confirm that if you use this option from a process running in a console, without piping stdout/stderr, the child process can still write to the console that it's in?

Yes, the proof is my post above: #346 (comment)

@takluyver

This comment has been minimized.

Copy link
Member

takluyver commented Apr 12, 2018

Sorry, that's not quite what I meant - I'm asking you to do it without stdout=subprocess.PIPE, stderr=subprocess.PIPE, and check that the child process can write directly to the console.

@nanoant

This comment has been minimized.

Copy link
Contributor Author

nanoant commented Apr 12, 2018

@takluyver Yes I now get your point, let me rework the patch so it takes this countermeasure only for pythonw which is already checked at the top of the function.

When running Jupyter via pythonw e.g. pythonw -m qtconsole, jupyter_client launches new kernel via python.exe which is a console application on Windows - a side-effect of that is a new empty console window created and shown as long as kernel is running.

This patch adds CREATE_NO_WINDOW 0x08000000 to Windows specific creationflags. This flag is not exported by subprocess module therefore has to be provides numerically.
@nanoant nanoant force-pushed the nanoant:master branch from a69bc5c to bf57d23 Apr 12, 2018
@takluyver

This comment has been minimized.

Copy link
Member

takluyver commented Apr 12, 2018

Thanks, that looks good to me now. :-)

@takluyver takluyver merged commit b754994 into jupyter:master Apr 12, 2018
1 check passed
1 check passed
continuous-integration/travis-ci/pr The Travis CI build passed
Details
meeseeksdev bot pushed a commit that referenced this pull request Apr 12, 2018
takluyver added a commit that referenced this pull request Apr 12, 2018
Backport PR #346 on branch 5.x
@nanoant

This comment has been minimized.

Copy link
Contributor Author

nanoant commented Apr 12, 2018

@takluyver Thanks a lot! Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.