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

reuse $DISPLAY variable #8

Open
esaulenka opened this issue Aug 8, 2022 · 13 comments
Open

reuse $DISPLAY variable #8

esaulenka opened this issue Aug 8, 2022 · 13 comments
Labels
enhancement New feature or request

Comments

@esaulenka
Copy link

Hello Martin!

Could you enhance your script to get IP / display number from DISPLAY variable ?

How do I want to use it:
I need only one X-Server on my machine (I think it is most popular option)
set $DISPLAY=127.0.0.1:bla-bla always on startup in bashrc
start X-Server manually, when I need it
run clients from several terminals

@esaulenka
Copy link
Author

as a workaround, I wrote in my .bashrc simple alias:

# run X Server
alias runx='/usr/local/bin/runx --no-auth --ip 127.0.0.1 --display 123 &'
export DISPLAY=127.0.0.1:123

@mviereck
Copy link
Owner

mviereck commented Aug 8, 2022

Thank you for your feedback!
Your workaround looks well.
I am not sure yet how I could improve runx here.
Parsing DISPLAY is no good way to go, because, by definition, it should point to an already running X server.

Maybe an option to check existing DISPLAY if there is an X server already running, and only run a new one if there is none, would be a way.
However, I am not sure how to check if there is an X server available already.
If I had an X tool, let's say e.g. xwininfo, I could run it to see if it succeeds to access X.
But MSYS2 provides no X tools at all. And I have no idea yet how to check with bash only.

What happens if you just run your runx alias although runx is running already? Maybe it could be ok to let it fail if DISPLAY is already in use.

@mviereck mviereck added the enhancement New feature or request label Aug 8, 2022
@mviereck
Copy link
Owner

mviereck commented Aug 8, 2022

But MSYS2 provides no X tools at all. And I have no idea yet how to check with bash only.

One idea: runx could run a check with telnet.
However, I don't know if telnet can be expected to be available in MSYS2, Cygwin and WSL by default.

The port number to access X is 6000+displaynumber. In your example it would be 6123.
Please check the output of:

echo hello | telnet 127.0.0.1 6123

If it succeeds, you should see a line Connected to 127.0.0.1.

@esaulenka
Copy link
Author

Maybe an option to check existing DISPLAY if there is an X server already running, and only run a new one if there is none, would be a way.

No, it doesn't work the way I expect. When I run a new terminal, it doesn't inherit variables from other one, so I have DISPLAY only in first one.

What happens if you just run your runx alias although runx is running already?

It doesn't work too. Author of VcXsrv didn't expected that anyone will run two copies of it with same port. So, it shows a window with a fatal error message.

One idea: runx could run a check with telnet.

Yes, it works as you describe:

$ echo hello | telnet 127.0.0.1 6123
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.

On MSYS2 telnet is a part of one of base packages, and base depends on this package.

I understand your explanation, thanks. I think would be better to close this issue without changes in runx logic.

@mviereck
Copy link
Owner

mviereck commented Aug 8, 2022

I understand your explanation, thanks. I think would be better to close this issue without changes in runx logic.

I am working at a solution. Could you test this runx script stored at pastebin? https://pastebin.com/5FjmDqqp

The idea is: If you run runx with --display=123, it checks with telnet if the display number is already in use.
If yes, runx does not start an X server but only sets DISPLAY and XAUTHORITY to likely correct values.

So, if you have a line in your .bashrc like:

source /usr/local/bin/runx --no-auth --ip 127.0.0.1 --display 123 

Once you open a terminal, this should run an X server in background and set DISPLAY (and XAUTHORITY if you omit --no-auth).
If you open a second terminal, .bashrc will run runx again, but runx will only set the variables without running a new X server.

@esaulenka
Copy link
Author

Thanks, it works as you describe.
Some remarks: telnet wrote "Connection closed by foreign host" to stderr. I think would be better to hide it.
When X-Server already started, runx spends whole 2.5 seconds just to check it (and 2.0 seconds of them - to open telnet). So, I don't want to include it to my .bashrc for each terminal I run.

@mviereck
Copy link
Owner

mviereck commented Aug 9, 2022

Thanks, it works as you describe.

Good news!

Some remarks: telnet wrote "Connection closed by foreign host" to stderr. I think would be better to hide it.

Good point, it's done.

When X-Server already started, runx spends whole 2.5 seconds just to check it (and 2.0 seconds of them - to open telnet).

Oh, ok. So telnet is too slow here. (On debian it responds pretty fast.) Likely the delay is caused by DNS resolving.
On the runx side I've made some changes that should speed up the start (notably less dependency checks because MS Windows is known to have poor file system access performance).

Let's try some hopefully faster alternatives to the current telnet solution.
Please try the following port checks with an already open display port (like 6000+123 as in your example) and with a closed port, maybe 6500. Please check if it works at all, and if the delay is reasonable.

A bash internal TCP access feature:

bash -c "</dev/tcp/127.0.0.1/6123 ; echo $?"
bash -c "</dev/tcp/127.0.0.1/6500 ; echo $?"

Another attempt using netcat:

nc -z -n 127.0.0.1 6123 ; echo $?
nc -z -n 127.0.0.1 6500 ; echo $?

Another telnet attempt:

echo "quit" | telnet 127.0.0.1 6123
echo "quit" | telnet 127.0.0.1 6500

perl:

perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("127.0.0.1:6123")))' ; echo $?
perl -MIO::Socket::INET -e 'exit(! defined( IO::Socket::INET->new("127.0.0.1:6500")))' ; echo $?

nmap:

nmap -n 127.0.0.1 -p 6123
nmap -n 127.0.0.1 -p 6500

If one of them is reasonable fast, I would replace the current telnet code with it. I would favorize the bash solution with the virtual /dev/tcp path because it avoids additional dependencies.

@esaulenka
Copy link
Author

Sorry, it is a my mistake.

So, on MSYS telnet works fast when socket already open (only 35 millisec). Maybe I tried to connect to closed socket (in this case telnet hangs for 2 seconds).
Checking for /dev/tcp gives almost same results. I dont have perl and nmap, and I didnt checked it.

But issue with a slow running is still here.

$ time source /usr/local/bin/runx --ip 127.0.0.1 --display 123
DISPLAY=127.0.0.1:123 XAUTHORITY=/home/alexeye/runx_Xauthority

real    0m1.876s
user    0m0.363s
sys     0m1.227s

I have not a much experience with bash, could you explain how to benchmark it ?

mviereck added a commit that referenced this issue Aug 12, 2022
@mviereck
Copy link
Owner

mviereck commented Aug 12, 2022

Thank you for the tests! I have replaced telnet with the /dev/tcp code.

I have not a much experience with bash, could you explain how to benchmark it ?

There is no ready solution for bash benchmark tests.
As a quick attempt you can run bash -x /usr/local/bin/runx [...] or add set -x in the code. This causes bash to print every command before it is executed.
If a single command takes very long (like telnet with unresponsive ports on Windows), it would be visible to the eye.
You can also add runx option --verbose to get an idea of script progress.

So, I don't want to include it to my .bashrc for each terminal I run.

Instead of sourcing at each startup you could still use an alias.
The alias could contain source as well. Than at least you would not need to set DISPLAY manually. (The source setup allows runx to export DISPLAY and XAUTHORITY).

@esaulenka
Copy link
Author

As a quick attempt you can run bash -x /usr/local/bin/runx [...] or add set -x in the code. This causes bash to print every command before it is executed.

Unfortunately, it doesn't helps. I cannot see any significant gaps between messages, but whole run time is still 1.7 .. 2.0 seconds

Looks like MSYS bash just compiled without speed optimizations (but with simple scripts it runs fine).
Maybe, will be better to use native WSL (for a some reasons I should use Windows OS and Linux apps on my work note)...

@esaulenka
Copy link
Author

Thank you for the tests! I have replaced telnet with the /dev/tcp code.

@mviereck Martin, by the way, issue with message to stderr appeared again:

$ source runx
C:\msys64\usr\bin\bash: connect: Connection refused
C:\msys64\usr\bin\bash: /dev/tcp/192.168.56.1/6461: Connection refused
DISPLAY=192.168.56.1:461 XAUTHORITY=/c/Users/alexeye/Xauthority.runx

@mviereck
Copy link
Owner

mviereck commented Aug 17, 2022

issue with message to stderr appeared again:

That's odd. It seems I cannot supress the error message:

$ </dev/tcp/127.0.0.1/6000 >/dev/null 2>/dev/null
bash: connect: Verbindungsaufbau abgelehnt
bash: /dev/tcp/127.0.0.1/6000: Verbindungsaufbau abgelehnt

Edit:
I could fix it like:

$ (</dev/tcp/127.0.0.1/6000) >/dev/null 2>&1

@mviereck
Copy link
Owner

mviereck commented Aug 18, 2022

runx now stores DISPLAY and XAUTHORITY in file ~/.Xenv.

To re-use an already running X server, it is enough to source the file with . ~/.Xenv or source ~/.Xenv.
This avoids the long delay that sourcing runx at each terminal start would cause.

So if you need an X server, just run

source runx

To use the X server in another terminal, run:

source ~/.Xenv

The line source ~/.Xenv could even be added to ~/.bashrc. So if you run source runx in your first terminal, all follow-up terminals will be able to access the X server immediately.

You would not need to (but still can) specify IP or display number in the runx command.
Specifying the IP number would at least save a bit of startup time because ipconfig.exe won't be called.
And with specified IP+displaynumber the content of ~/.Xenv would always be the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants