Detect whether wineserver is fully started? Signal? File?

Sebastian M. Ernst ernst at pleiszenburg.de
Sat Jun 17 05:20:25 CDT 2017


@Bruno

> Not sure if I got the problem you are describing exactly but what
> about doing the opposite direction? Make a very simple socket program
> for Windows that is launched and this program connects to your python
> application instead. When python notices the connection it is sure
> that wineserver is running because it just received the connection
> from an app running inside Wine. Also as long as this small utility is
> up wineserver won't close too.

Thanks, yes, I have considered this approach (and will likely follow it
if everything else does not work). I'd prefer a "pythonic" solution
without adding dependencies like a cross-compiler (for compiling the
utility) to my module. I am already doing this for tests, but I'd really
like to keep the module itself "clean" and easy to install. Just as a
theoretical question, could such a utility be implemented as a batch
file which wine (cmd) could handle "out of the box"?

@Sebastian

thanks again, this is really helpful.

> If you disconnect before the real command is started the wineserver will
> assume it is no longer needed and terminate automatically. I would say
> this is a bug, because the user definitely does not expect that when
> passing "-p". 

Is this worth opening a ticket?

> Nevertheless, when you keep the connection open, it should
> actually work (and also does work for me, according to a quick test).

Once my wineserver is up, I try to do a number of path conversion using
"winepath -w /some/path" etc. first before I fire up any exe-files. Am I
correct in assuming that winepath should also use my wineserver (if run
with the same prefix)? Can you check whether your quick test also works
with winepath (eliminating a potential source of error)? I managed to
turn winepath directly into a zombie a number of times by running
winepath (too early) while wineserver was still starting. It does not
produce any error messages whatsoever.

> A slightly better solution which does not trigger this problem would be
> to wait for the wineserver lock (which will also appear in the server dir).

I used your code and implemented a routine which waits for the lock-file
to be locked - see below this email. Usually, it requires two attempts /
about 0.01 seconds until it succeeds. The PID returned by your code
matches the PID of my wineserver. The problem is, just after I have
confirmed the lock, winepath becomes a zombie again and again and ...
occasionally, it works. Is this a bug or a lack of understanding on my part?

> There is still a small race-condition (the lock is acquired but the socket
> has not been created yet), but Wine will be able to deal with that. It will
> retry a couple of times until it finally succeeds.

Could a failure in this mechanism be the reason for my zombies? (Happens
with Wine 2.5, 2.6 and 2.10.)

> BTW: As I saw, you replaced the "/tmp" with tempfile.gettempdir(), but this
> is actually not correct. Wineserver sockets will always be created in /tmp
> (hardcoded in the source) to ensure the correct socket is found, no matter
> which environment variables are set.

I did not expect that ... thanks.

Best regards,
Sebastian



# Get full path of socket
lock_path = os.path.join(self.server_path, 'lock')

# Status log
self.log.out('[wine session] Expecting wineserver lock at %s ...' %
lock_path)

# Status variable
got_lock_pid = False
# Time-step
wait_for_seconds = 0.01
# Timeout
timeout_after_seconds = 30.0
# Already waited for ...
started_waiting_at = time.time()
# Connection trys
tried_this_many_times = 0

# Run loop until socket appears
while True:

	# Does socket file exist?
	if os.path.exists(lock_path):

		# Count attempts
		tried_this_many_times += 1

		# Open lock file
		lock_file = open(lock_path, 'rb')
		# Can I retrieve a PID?
		lock_pid = self.__get_lock_pid__(lock_file)
		# Close lock file
		lock_file.close()

		# Check result
		if lock_pid is not None:
			got_lock_pid = True
			break

	# Break the loop after timeout
	if time.time() >= (started_waiting_at + timeout_after_seconds):
		break

	# Wait before trying again
	time.sleep(wait_for_seconds)

# Evaluate the result
if not got_lock_pid:

	self.log.out(
		'[wine session] ... was not locked %d (after %0.2f seconds & %d
attempts)! Quit.' % (
			timeout_after_seconds, tried_this_many_times
			)
		)
	sys.exit()

else:

	# Log status
	self.log.out(
		'[wine session] ... is locked by PID %d (after %0.2f seconds & %d
attempts)!' % (
			lock_pid, time.time() - started_waiting_at, tried_this_many_times
			)
		)



More information about the wine-devel mailing list