I have a fairly simple \"Hello World\" in X11 at end of question. But when it exits I get the run time error messages below:
$ ./xtest
XIO: fatal IO error 11 (R
I had the same problem, and after digging through Xlib documentation and a lot of experimenting I think I know the answer to your question and I can explain it to you.
When you call XCreateWindow
or XCreateSimpleWindow
and then XMapWindow
, you instruct the X Server to create your window and map in onto the screen. After sending these commands from the local buffer to the server (by calling XFlush
or any function which requests some data from the server, since it implicitly flushes the command buffer), the X Server displays your window. Then it's a job of the Window Manager to attach all the decorations to your window, e.g. some borders, title bar, window menu and those buttons to minimize/maximize/close the window.
Now your window is being displayed, and after a while you can decide to destroy it with XDestroyWindow
and close the connection to the X Server by calling XCloseDisplay
, and everything will be fine, no errors.
The problem is that when the user clicks on that X on your window's title bar, it is not the job of the X Server to handle it, but the Window Manager's job (the X Server knows nothing about those decorations and it doesn't care). The usual reaction of the Window Manager when the user closes the top-level window of your program is to destroy the window and close the connection to the X Server, because that's what most users would expect. Your program may still run off-screen, but the top-level window is usually associated with the X Server connection by the Window Manager.
So when the Window Manager destroys your window, you cannot call XDestroyWindow
, because the window is already destroyed and its Window
handle is invalid. You will get an error about BadWindow
. You also cannot call XCloseDisplay
, because the connection to the X Server is already closed, and this will cause the XIO: fatal IO error 11 (Resource temporarily unavailable) on X server
error many users experience from applications whose authors didn't knew that. It is a common mistake, because in one hand you are encouraged to clean up after yourself, but in the other hand the documentation is misleading about how this should be done properly.
There is a convention, though, about how X Server and Window Manager should cooperate, which also covers responding to user's commands to close the top-level window. There's an extension to the X protocol that handles it. Here's how the Xlib documentation explains it:
Clients, usually those with multiple top-level windows, whose server connection must survive the deletion of some of their top-level windows, should include the atom
WM_DELETE_WINDOW
in theWM_PROTOCOLS
property on each such window. They will receive aClientMessage
event as described above whosedata[0]
field isWM_DELETE_WINDOW
.
[...]
Clients that choose not to includeWM_DELETE_WINDOW
in theWM_PROTOCOLS
property may be disconnected from the server if the user asks for one of the client's top-level windows to be deleted.
So there are two solutions to this problem: either avoid calling XDestroyWindow
and XCloseDisplay
when your window is being closed by the Window Manager and not by yourself (you actually don't have to clean up the top-level window since the X Server will destroy it nevertheless when your program ends), or you need to register the WM_DESTROY_WINDOW
extension and wait for notification from the Window Manager when it is instructed by the user to close your window (it will send you a ClientMessage
event then, with its data[0]
set to WM_DELETE_WINDOW
). And after receiving it just destroy the window and close the connection to the X Server yourself, and end your program. Or leave the connection to the X Server open to perform some more communication with it if you wish. When you handle WM_DESTROY_WINDOW
, the Window Manager will not try to destroy your window nor close the connection to the X Server.