From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Michael Albinus Newsgroups: gmane.emacs.bugs Subject: bug#25214: 26.0.50; Interacting with user from threads other than the primary Date: Mon, 17 Sep 2018 16:06:07 +0200 Message-ID: <87zhwguskw.fsf@gmx.de> References: <837f6z9a4x.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1537193110 15871 195.159.176.226 (17 Sep 2018 14:05:10 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 17 Sep 2018 14:05:10 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) Cc: 25214@debbugs.gnu.org, Tom Tromey To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Sep 17 16:05:06 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1u9B-0003zL-PS for geb-bug-gnu-emacs@m.gmane.org; Mon, 17 Sep 2018 16:05:05 +0200 Original-Received: from localhost ([::1]:35753 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1uBI-000860-Ed for geb-bug-gnu-emacs@m.gmane.org; Mon, 17 Sep 2018 10:07:16 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60458) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g1uBB-00085g-2f for bug-gnu-emacs@gnu.org; Mon, 17 Sep 2018 10:07:10 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g1uB4-00052k-Ko for bug-gnu-emacs@gnu.org; Mon, 17 Sep 2018 10:07:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:38961) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g1uB4-00051n-De for bug-gnu-emacs@gnu.org; Mon, 17 Sep 2018 10:07:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1g1uB4-00059W-8F for bug-gnu-emacs@gnu.org; Mon, 17 Sep 2018 10:07:02 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: <837f6z9a4x.fsf@gnu.org> Resent-From: Michael Albinus Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 17 Sep 2018 14:07:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 25214 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 25214-submit@debbugs.gnu.org id=B25214.153719319219770 (code B ref 25214); Mon, 17 Sep 2018 14:07:02 +0000 Original-Received: (at 25214) by debbugs.gnu.org; 17 Sep 2018 14:06:32 +0000 Original-Received: from localhost ([127.0.0.1]:43219 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1uAa-00058n-0H for submit@debbugs.gnu.org; Mon, 17 Sep 2018 10:06:32 -0400 Original-Received: from mout.gmx.net ([212.227.15.15]:45153) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1g1uAY-00058Z-Gp for 25214@debbugs.gnu.org; Mon, 17 Sep 2018 10:06:30 -0400 Original-Received: from detlef.gmx.de ([212.91.249.153]) by mail.gmx.com (mrgmx003 [212.227.17.190]) with ESMTPSA (Nemesis) id 0Lbujs-1faEKM2vFk-00jGsu; Mon, 17 Sep 2018 16:06:10 +0200 X-Provags-ID: V03:K1:kYQmBzU7L7nXQZso0ZOMtVo3TpwxamKt1MpBoGmZlo+myjyfUjM mIPxmq329VflDRiNvbfK7fkw5ECc6/5jH/fHQcRy9i9zOdMZICctcfyq2RXFyzFVjWmqrwO btbNXCAsdCvHZKZqFPQX2gEmZR7qdz2pbbgc1H4C3ToJgW5gjUT8JSox6mjDtKirUYKOg0j uMfdCh3oKzEALEuZFt7qA== X-UI-Out-Filterresults: notjunk:1;V01:K0:rOQtXO6KPPI=:vTobkOKrtGZkAQfhcILGip 4COc0vvHK9WHuwvwlo/4hiEleHRDbYnbLECUHT4+E1TtKj0Ez3kcXKqpLfEh8tas1GFdILpEx m4YFeQQhTFAKe9ocTsiTKTofin4WXA9asifuMETj/fyR8YYmxGGMulgssBYAk6AOx7NKbmuj1 FRZx16CWe01Ce+i5ilUcGnBmZTqJLCS5shAJei1oBabvTcJLTgBYgsxewtHK9mjB2hl6JGNSx Aspg9b+/dF3kcyKr8yu83PXYuUtsZwwf6mgXJaXHdDrGOdVsV4sowUB+6YpCgRvYYHXGZRNDp QkVDDikpUV8syG06BBa9y9isVNto63q24vJ57i7DYQ7i5S5fnwPeaF4Mf2OqBVEmLnRsXFPLz UegxYurOkID1iEFDmRBLbEE4wJbWrZ3vSCuuzjo3+W2hg0A6vBoUFVhVLcZ0UtBrA7gFbLk/e 5L+locxLTsg+A8cRm1TSXvB0o4eQIu3nMcJpqI/eOaNynEJ0hsvpjBvzIZgEBZuAOYj1eD/0O 1HzRRGh8W9rjFDyBVHqmXYowJ7E4PjaeQY7BToa1NrYC8xuaLs107cdCmG997XF/jSjqmn/ps +Zu+Izdbxef+jI2eJUXX7qbVlg+qYKF83zCjsXVqBMm3ze1npwjZNdb3xM//hizRmXeDgGttT RtmCiVx2l0XKiN9uIeHmvFXozFHQhE5NcYgAoY2OH2Yfmmsdt7pk/ZtoPfs3VJG/q7A/6Vrtz v/5k5k/vuW+4DXWpHyFqwSLss/h8jhAIZdL3n+jmev/HLkge3jGh/IGGh69cqh6gArhkqwgX X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:150367 Archived-At: Eli Zaretskii writes: > Here's some fun with threads: > > emacs -Q > > Evaluate: > > (defun my-question () > (let (use-dialog-box) ;; in case this is a GUI frame > (if (y-or-n-p "Yes or no? ") > (message "You said YES") > (message "You said NO")))) > > Now evaluate this: > > (make-thread #'my-question "question") > > You again get the question asked in the minibuffer, but typing > anything at the prompt causes Emacs to complain that whatever you > typed is "undefined". Your only fire escape is to close this session > with some mouse gesture, or kill it. > > What happens here is that, by the time the new thread runs, the main > (a.k.a. "primary") thread is already idle, i.e. it already called > read_char, which called wait_reading_process_output, which called > thread_select. (In fact, it's _because_ the primary thread called > thread_select that the new thread was allowed to run at all, since it > has to acquire the global lock for that, and that is only possible > when the running thread releases the lock inside thread_select.) Now, > when wait_reading_process_output calls thread_select, it prepares the > mask for file descriptors it will wait for to become ready for > reading, in this case there's only one descriptor: the keyboard > descriptor. So the primary thread is waiting for input from the > keyboard. > > Now the new thread starts running and eventually calls y-or-n-p, which > calls read_char, which calls wait_reading_process_output. But when > this call prepares the mask for the thread_select call, it skips the > keyboard descriptor, because we only allow a single thread to wait on > each descriptor, and the keyboard descriptor is already watched by the > primary thread. So the new thread ends up not waiting on the keyboard > input descriptor. > > The thread_select call then switches back to the primary thread, and > the primary thread receives the Y or N character you type. But it > doesn't know what to do with it, so it becomes confused. > > IOW, user interaction from non-primary threads is currently inherently > unsafe. IOW, user interaction from non-primary threads is currently inherently impossible. I've tried to understand the mechanism in process.c, and I summarize it (mainly for my understanding, but also to give you a chance to correct me). 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. 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. > And then, of course, there's the use case where two threads ask the > user something via the minibuffer. This scenario shall also be possible then. > Thoughts? Here I am :-) Best regards, Michael.