Due to an influx of spam, we have had to impose restrictions on new accounts. Please see this wiki page for instructions on how to get full permissions. Sorry for the inconvenience.
libX11 stashes away a XID (in display->xcb->next_xid) to be used later. However, when xcb uses up its ID range, it will make a GetXIDRange request to retrieve the free XIDs from the xserver. Because the XID stashed away by libX11 is not actually used, it's considered free by the xserver. Thus, xcb_generate_id() and XAllocID will both return that ID later, causing BadIDChoice.
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Child items
...
Show closed items
Linked items
0
Link issues together to show that they're related.
Learn more.
This comes with the realization that, in multithreaded xcb applications, all resource creation requests would have to be guarded by locks. Otherwise BadIDChoice could occur. I wonder if it's common practice to do this.
Reason:
thread A: thread B:id_a = xcb_generate_id() // Assuming this call causes xcb to send GetXIDRange; // After this, xcb thinks id_a is free again. id_b = xcb_generate_id() // ... a couple of xcb_generate_id() later ... // xcb returns id_a again, so here id_b2 == id_a id_b2 = xcb_generate_id() xcb_create_something_checked(id_b2)// This request fails with IDChoicexcb_create_something_checked(id_a)
Have xcb_generate_id lock a mutex (counting, in case there are multiple IDs) which is unlocked by the xcb_create_... call. This gets complicated if the thread exits with the mutex locked ...
Record the ID as in-use by xcb_generate_id and remove those values from the GetXIDRange reply. Remove this record when the xcb_create call is invoked, or when the thread exits using pthread thread-specific data functions (pthread_key_create et al.)
Not bothering with the whole thread-specific data is not completely out of the question; we'll lose XIDs in proportion to the number of threads which exit between the xcb_generate_id and the xcb_create_... calls
Random data point: Cairo's XCB code caches free XIDs. The only code to xcb_generate_id() is in src/cairo-xcb-connection.c, function _cairo_xcb_connection_get_xid(). It only calls the function if the cache is empty. This is the code:
I guess this code cannot work in a world where GetXIDRange exists, or does anyone see a possibility? If not, how should the docs be worded to make cairo's code wrong?
For now, just deleting this code in cairo would be a good start; that reduces the vulnerable window to the time between a pair of XCB calls. That will then let us fix xcb to close the remaining gap. If XID allocation is really a performance concern, we could re-implement this kind of caching under the covers in xcb.
The xcb design separating ID allocation from resource creation looks like a poor design choice at this point, doesn't it...