Subject: Re: bug#25214: 26.0.50; Interacting with user from threads other than the primary

From: Eli Zaretskii <[email-masked]>
Date: Mon, 17 Sep 2018 21:41:47 +0300

> From: Michael Albinus <[email-masked]>
> Cc: [email-masked],  Tom Tromey <[email-masked]>
> Date: Mon, 17 Sep 2018 16:06:07 +0200
> 
> The fd mask is controlled by fd_callback_info, an array (indexed by
> fd's) over the struct fd_callback_data. There are two relevant struct
> fields: thread and waiting_thread. thread is set in Fset_process_thread
> for the infd and outfd file descriptors of the process, it shall be NULL
> in the example given above.
> 
> waiting_thread is always set to current_thread, in the
> compute_input_wait_mask, compute_non_process_wait_mask,
> compute_non_keyboard_wait_mask and compute_write_mask functions. The
> condition is always, that waiting_thread is either NULL or
> current_thread.
> 
> A file descriptor, be it for the keyboard or process related or
> whatever, is only taken into account during setting an fd_mask, when
> either both thread and waiting_thread are NULL, or when one of the
> struct fields is set to a thread, being equal to the current
> thread. IIUC, thead has precedence over waiting_thread, but this might
> be an implementation detail only. So far, it is expected that at least
> one of the fields is NULL.

That is correct, AFAIR.

> In order to fix the problem of reading input in a non-primary thread, we
> need a new function which request I/O control to the current thread. It
> needs
> 
> * to request control for the keyboard. This could be indicated by a
>   signal to the main thread, which is *not* an error signal but a
>   special one, let's call it `thread-set-keyboard'.
> 
> * to handle this signal in `thread-handle-event', by calling a
>   respective function (let's call it `thread--set-keyboard'). This
>   function sets the struct event thread to the thread which has
>   delivered by the `thread-set-keyboard' signal. Next time fd_mask is
>   prepared, the keyboard fd would be taken into account for the
>   requesting thread.
> 
> * to stop/recall the recent pselect for the main thread in order to free
>   the keyboard fd. Don't know how to do this.
> 
> * to provide a mechanism which resets the thread struct field of the
>   keyboard fd to NULL, in order to let the main thread use the
>   keyboard. Here I have also no idea how to do this.

It's not all we need (remember all that talk about serializing access
to the echo area?), but it's a beginning.  And the crucial piece is
bullet #3, because thread-signal will not interrupt the pselect call.
And if we are not too lucky, the pselect call could have been made
with a long timeout.  So this is the first obstacle to negotiate.

So what means do we have to interrupt a pselect call from another
thread?

(I'm not sure I understand why you thought we'd need bullet #2, btw.
Once we interrupt the pselect call, the main thread should become
stuck trying to take the global lock, so I don't think we need any
trickery here, because the other thread, which is running, will have
arranged for it to be the current thread.)

Thanks.