all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Eric Abrahamsen <eric@ericabrahamsen.net>
To: emacs-devel@gnu.org
Subject: Re: [RFC] Gnus generalized search, part II
Date: Sun, 30 Apr 2017 10:46:33 -0700	[thread overview]
Message-ID: <87a86x3i12.fsf@ericabrahamsen.net> (raw)
In-Reply-To: 8737d0ukev.fsf@ericabrahamsen.net

[-- Attachment #1: Type: text/plain, Size: 4258 bytes --]

Eric Abrahamsen <eric@ericabrahamsen.net> writes:

> Eli Zaretskii <eliz@gnu.org> writes:
>
> [...]
>
>>> Ideally there would be a message noting which search process was
>>> abandoned, which is another reason to use condition-case.
>>
>> You mean condition-case in the thread function?
>
> My original assumptions about how things work have mostly turned out
> wrong. So sure, inside the thread function! I need to set up some dummy
> shell programs and test this.

I finally got time to test this. I'm attaching a python script that I
used as the external process, and pasting below the code chunk I used
for testing. This is with emacs -Q, built from master this morning. I
opened a window on each of the three process buffers, and watched the
results come in. I'm not sure the `redisplay's are necessary, or a valid
measure of process response time, but it helped with eyeballing it.

Notes:

1. At first, I made the dumb mistake of writing "(dolist (t threads)" in
   the final loop. This caused emacs to segfault, and output the
   "attempt to set a constant" error on the command line. Obviously this
   is wrong, but it probably shouldn't segfault.
2. I tweaked the sleep time parameters in various ways, but so far as I
   can tell, output was returned correctly in all cases, even when the
   first thread was given the longest sleep time. When the earlier
   threads had shorter timeouts, sometimes the redisplay showed output
   coming in to their buffer buffer, sometimes it didn't. For my
   purposes this doesn't matter.
3. Keyboard quit does nothing at all. Nothing is interrupted, everything
   returns as normal.

So I played a bit with quitting. First, in the final dolist, I wrapped
each `thread-join' in a condition-case, which caught quit and used
`thread-signal' to send the quit to the thread.

The result was that the `thread-join' was quit, but not the thread or
its process. Ie, emacs stopped waiting on that thread and moved on to
the next one, but the process output still came in, and was inserted
into the correct buffer. Not too surprising, since the thread function
itself doesn't have any reason to pay attention to 'quit. I suppose that
this is okay in this setup, because the buffer has to exist: if the
buffer were deleted after the thread-join loop, the process would also
die.

But what about my actual use-case, where each thread is appending to the
value of a let-bound variable that is closed over in the thread
function? Say the longest thread-join is quit, the shorter thread-joins
return, and execution continues on in the main thread. We move out of
scope for the let-bound return variable, and then the last remaining
thread tries to set that variable. I'm guessing it'll segfault, but I
didn't try.

Then I added a second condition-case inside each thread function,
wrapping the `accept-process-output' call, catching quit, and using it
to call `kill-process' on "proc". So a keyboard quit gets first sent to
the thread function, and then on to the thread process. That behaved
pretty much the way I hoped it would, more or less. It was a crapshoot
which thread/process got killed, but they did get killed. Sometimes I
had to hit "C-g" several times before anything happened though. I wonder
if messing with `with-local-quit' or something could make that more
predictable.

Anyway, I found all this interesting -- hope it's useful to someone
else.


#+BEGIN_SRC emacs-lisp
(setq lexical-binding t)
(defvar test-threads)
(defvar thread-test-prog)
;; Name of thread, process buffer, seconds for thread-test-prog to
;; sleep.
(setq test-threads `(("one" ,(get-buffer-create "*thread one*") "2")
		     ("two" ,(get-buffer-create "*thread two*") "10")
		     ("three" ,(get-buffer-create "*thread three*") "3")))

(setq thread-test-prog (expand-file-name "~/.bin/threadtest.py"))

(let ((threads
       (mapcar
	(lambda (el)
	  (make-thread
	   (lambda ()
	     (let ((proc (start-process
			  (car el) (cadr el) thread-test-prog
			  "-t" (car el) "-s" (caddr el))))
	       (accept-process-output proc)))
	   (car el)))
	test-threads)))
  (dolist (el test-threads)
    (with-current-buffer (cadr el)
      (erase-buffer)))
  (dolist (th threads)
    (redisplay)
    (thread-join th)
    (redisplay)))
#+END_SRC


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: threadtest.py --]
[-- Type: text/x-python, Size: 365 bytes --]

#!/usr/bin/env python3

import time
import argparse

defsecs = 3

parser = argparse.ArgumentParser()
parser.add_argument("-t", "--thread")
parser.add_argument("-s", "--seconds", type=int)
args = parser.parse_args()

if not args.seconds:
    args.seconds = defsecs

time.sleep(args.seconds)
print("Process %s output (%s)" % (args.thread, time.strftime("%H:%M:%S")))

  reply	other threads:[~2017-04-30 17:46 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-21 21:35 [RFC] Gnus generalized search, part II Eric Abrahamsen
2017-04-22  0:16 ` Andrew Cohen
2017-04-22  5:27   ` Eric Abrahamsen
2017-04-22  8:08     ` Eli Zaretskii
2017-04-22 15:08       ` Eric Abrahamsen
2017-04-22 15:17         ` Eli Zaretskii
2017-04-22 15:25           ` Eli Zaretskii
2017-04-22 19:25           ` Eric Abrahamsen
2017-04-22 20:06             ` Eli Zaretskii
2017-04-22 22:50               ` Eric Abrahamsen
2017-04-30 17:46                 ` Eric Abrahamsen [this message]
2017-04-24 17:17             ` Stephen Leake
2017-04-26  9:42               ` Eli Zaretskii
2017-04-22 16:00         ` Noam Postavsky
2017-04-22  7:50   ` Eli Zaretskii
2017-04-22  8:00     ` Andrew Cohen
2017-04-22 19:53 ` Lars Ingebrigtsen
2017-04-22 20:26   ` Eric Abrahamsen
2017-04-24 20:30   ` Eric Abrahamsen
2017-04-26  4:41     ` Andrew Cohen
2017-04-26  9:21       ` Joakim Jalap
2017-04-26  8:18     ` Andrew Cohen
2017-04-26  8:22     ` Andrew Cohen
2017-04-23 13:48 ` Dan Christensen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87a86x3i12.fsf@ericabrahamsen.net \
    --to=eric@ericabrahamsen.net \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.