[PATCH xserver 2/6] Remove SIGIO support.

Peter Hutterer peter.hutterer at who-t.net
Wed Dec 9 14:40:40 PST 2015


On Wed, Dec 09, 2015 at 11:13:14AM -0800, Keith Packard wrote:
> Peter Hutterer <peter.hutterer at who-t.net> writes:
> 
> >>      /* Call PIE here so we don't try to dereference a device that's
> >>       * already been removed. */
> >> -    OsBlockSignals();
> >>      ProcessInputEvents();
> >> +    input_lock();
> >
> > this is a behaviour change, was this intended? I'd rather not have this
> > hidden in a giant patch that is otherwise mostly search and replace.
> 
> (I knew locking was the hard part...).
> 
> OsBlockSignals has a counter, so you can call it multiple
> times. input_lock is (going to be) a regular mutex, so you can't (and
> ProcessInputEvents definitely needs to hold the input lock). I moved
> this to eliminate a deadlock, only to now discover that xfree86's
> DeleteInputDeviceRequest grabs the input lock itself. And, kdrive's
> evdev driver calls DeleteInputDeviceRequest from the event reading code (!).
> 
> We may uncover more deadlocks in the code; I think each one in isolation
> should be pretty easy to fix. We could also implement a counter in the
> mutex? That would require using thread local storage, which is kinda
> ugly, but should at least allow the existing locking to not deadlock.
> 
> I'd rather work on annotating the code and data structures so that we
> know when the lock should be held; right now it's somewhat haphazard,
> with things like device property changes not taking the lock.
> 
> For instance, in this case we would mark the device as 'pending
> deletion' and have the event queuing code discard incoming events:
> 
>         input_lock();
>         dev->pending_deletion = TRUE;
>         input_unlock();
>         ProcessInputEvents();
>         input_lock();
>         DeleteInputDeviceRequest(dev);
>         input_unlock();
> 
> >> @@ -1077,8 +1077,8 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
> >>      InternalEvent *eventlist = InitEventList(GetMaximumEventsNum());
> >>      int i;
> >>  
> >> -    OsBlockSignals();
> >>      mieqProcessInputEvents();
> >> +    input_lock();
> >
> > same here. How about making the first patch all the search/replace cases and
> > let input_lock/unlock call OsBlockSignals/OsReleaseSignals. Then in the
> > second patch you can change the places where it needs to be moved around,
> > then in a third patch actually drop the signal handling.
> 
> For this case, mieqProcessDeviceEvent must not be called with the
> input_lock held as it (eventually) may call SetCursorPosition, which
> will grab input_lock to warp the cursor on the screen. 

yes, but you can do that with the suggestion above. do a straightforward
search/replace for OsBlockSignals -> input_lock, then when you drop 
OsBlockSignals from input_lock you can move things where needed. plus you
get to see the places where the reordering was needed stand out.
[ok, now that I read the rest of the email I see you're suggesting to do
this further below]

> Given what this
> function does, it seems like it is equivalent to:
> 
>     input_lock();
>     for (i = 0; i < dev->last.num_touches; i++) {
>         DDXTouchPointInfoPtr ddxti = dev->last.touches + i;
> 
>         if (ddxti->active)
>             QueueTouchEvents(dev, XI_TouchEnd, ddxti->ddx_id, 0, NULL);
>     }
>     input_unlock();
>     ProcessInputEvents();
> 
> Similarly, ReleaseButtonsAndKeys should be changed to queue the relevant
> events under the lock and then process them. That's a bit harder as that
> function is looking at the logical state of the device, not the physical
> state. It looks like that's just the tip of a large bug though -- a
> frozen device that gets removed is going to have events in the
> syncEvents list still pointing at it. That seems bad...
> 
> >> +xf86ReadInput(int fd, int ready, void *closure) {
> >
> > new line for {, no empty line before static void
> 
> Thanks.
> 
> >> diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
> >> index c42e93e..b506338 100644
> >> --- a/hw/xfree86/common/xf86Helper.c
> >> +++ b/hw/xfree86/common/xf86Helper.c
> >> @@ -1729,7 +1729,7 @@ xf86SetSilkenMouse(ScreenPtr pScreen)
> >>       * yet.  Should handle this differently so that alternate async methods
> >>       * work correctly with this too.
> >>       */
> >> -    pScrn->silkenMouse = useSM && xf86Info.useSIGIO && xf86SIGIOSupported();
> >> +    pScrn->silkenMouse = useSM && FALSE;
> >
> > wait, what?
> 
> It's a temporary hack -- having removed SIGIO and not replaced it with
> threading, all of the 'silken mouse' code can't actually work. Once we
> add threads, then this looks sensible again.

add a comment please, if for no other reason than to reduce confusion of
those who look at the patches separately.

> 
> >>  libbsd_la_SOURCES = \
> >>  	$(srcdir)/../shared/posix_tty.c \
> >> -	$(srcdir)/../shared/sigio.c \
> >>  	$(srcdir)/../shared/vidmem.c \
> >>  	bsd_VTsw.c \
> >>  	bsd_init.c \
> >
> > [...]
> 
> I split the DRI1 breakage and SIGIO API removal out into separate
> patches so we can discuss whether DRI1 needs to be supported independently
> of whether input should be threaded.
> 
> >> diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
> >> index aeb702c..effda7c 100644
> >> --- a/xkb/xkbActions.c
> >> +++ b/xkb/xkbActions.c
> >> @@ -1526,7 +1526,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
> >>          return;
> >>  
> >>      events = InitEventList(GetMaximumEventsNum() + 1);
> >> -    OsBlockSignals();
> >> +    input_lock();
> >>      pScreen = miPointerGetScreen(ptr);
> >>      saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
> >>      nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
> >> @@ -1534,10 +1534,10 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
> >>          UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
> >>                           &nevents);
> >>      miPointerSetWaitForUpdate(pScreen, saveWait);
> >> -    OsReleaseSignals();
> >>  
> >>      for (i = 0; i < nevents; i++)
> >>          mieqProcessDeviceEvent(ptr, &events[i], NULL);
> >> +    input_unlock();
> >
> > again, a change in behaviour here
> 
> And this one is wrong even -- mieqProcessDeviceEvent needs to be called
> with input_lock not held (as above).
> 
> > Cheers,
> >    Peter
> 
> Thanks so much for reading through this. I think what I want to do is
> provide a patch which continues to use OsBlockSIGIO/OsReleaseSIGIO but
> fixes all of the recursive locking issues, then switches those (with a
> sed script) to input_lock()/input_unlock(). Seem reasonable?

yeah, that sounds fine to me, thanks.

Cheers,
   Peter


More information about the xorg-devel mailing list