unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Single process output reading
@ 2004-08-16  9:21 Milan Zamazal
  2004-08-16 14:37 ` Kim F. Storm
  2004-08-18  1:34 ` Richard Stallman
  0 siblings, 2 replies; 10+ messages in thread
From: Milan Zamazal @ 2004-08-16  9:21 UTC (permalink / raw)


I think a way to read an output of just a single asynchronous process in
Emacs is needed.  I.e. a way to invoke accept-process-output without
possible invocation of another process filter function or a timer.

Why is it needed?  Currently, there's no way to do it AFAIK, which
basically means that all process filter functions must be reentrant.
Making a process filter function reentrant is not always a trivial task
and it's useless to do so except that the scenario like the following
one can happen:

A process filter function `foo' is invoked.  It reports about the
process reading progress via the `message' function.  `message' can be
advised, e.g. by some speech output function.  The speech output
function communicates with a speech synthesizer through a network
process and it calls accept-process-output to read the synthesizer's
answer.  But within the accept-process-output, `foo' can be invoked
again.  If it is not reentrant, errors can happen.

This is what actually happens in the speechd-el speech output system
which, among others, advises the `message' function.  So any filter
function calling `message' (or doing some other actions handled by the
speech output system) is fragile to this problem.

There's a workaround for this: To write an external program resending
the data/answer to/from the desired network connection and to call this
program synchronously from Emacs (anytime a piece of data is to be sent
to the network connection) with call-process.  This is what I actually
did, but I don't think it's a good way of solving the problem, both from
the point of view of the programmer and the user.

IMO a better way would be to allow restricting accept-process-output to
just a single process output reading.  Then the speech output system,
aware of possible consequences of advising 'message' etc., could invoke
accept-process-output in the restricted form, without the danger of
unwanted side effects.

I need this feature, so I'm willing to implement it unless someone more
competent would like to do it.

My questions are:

- Do you agree with my analysis or do you have a better suggestion how
  to solve the presented problem?

- Do you have some suggestions how the restricted invocation of
  accept-process-output might look?  New optional argument?

- Do you have some implementation advice?

Thanks for any help.

Regards,

Milan Zamazal

-- 
http://www.zamazal.org

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-16  9:21 Single process output reading Milan Zamazal
@ 2004-08-16 14:37 ` Kim F. Storm
  2004-08-17 11:31   ` Milan Zamazal
  2004-08-18  1:34 ` Richard Stallman
  1 sibling, 1 reply; 10+ messages in thread
From: Kim F. Storm @ 2004-08-16 14:37 UTC (permalink / raw)
  Cc: emacs-devel

Milan Zamazal <pdm@brailcom.org> writes:

> I think a way to read an output of just a single asynchronous process in
> Emacs is needed.  I.e. a way to invoke accept-process-output without
> possible invocation of another process filter function or a timer.

Your reasons sound valid to me, but blocking everything including timers
isn't very good, but may be acceptable for very short periods of time.

> IMO a better way would be to allow restricting accept-process-output to
> just a single process output reading.  Then the speech output system,
> aware of possible consequences of advising 'message' etc., could invoke
> accept-process-output in the restricted form, without the danger of
> unwanted side effects.

Here's an (untested) patch that adds a "just-this-one" arg to
accept-process-output

To avoid running timers, specify an integer as fourth arg, e.g.
  (accept-process-output your-process nil nil 1)


*** process.c	29 Jul 2004 16:46:31 +0200	1.434
--- process.c	16 Aug 2004 16:25:16 +0200	
***************
*** 3718,3734 ****
  }
  \f
  DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
!        0, 3, 0,
         doc: /* Allow any pending output from subprocesses to be read by Emacs.
  It is read into the process' buffers or given to their filter functions.
  Non-nil arg PROCESS means do not return until some output has been received
  from PROCESS.
  Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of
  seconds and microseconds to wait; return after that much time whether
  or not there is input.
  Return non-nil iff we received any output before the timeout expired.  */)
!      (process, timeout, timeout_msecs)
!      register Lisp_Object process, timeout, timeout_msecs;
  {
    int seconds;
    int useconds;
--- 3718,3737 ----
  }
  \f
  DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
!        0, 4, 0,
         doc: /* Allow any pending output from subprocesses to be read by Emacs.
  It is read into the process' buffers or given to their filter functions.
  Non-nil arg PROCESS means do not return until some output has been received
  from PROCESS.
+ If optional fourth arg JUST-THIS-ONE is non-nil, only accept output
+ from PROCESS, suspending reading output from other processes.
+ If JUST-THIS-ONE is an integer, don't run any timers either.
  Non-nil second arg TIMEOUT and third arg TIMEOUT-MSECS are number of
  seconds and microseconds to wait; return after that much time whether
  or not there is input.
  Return non-nil iff we received any output before the timeout expired.  */)
!      (process, timeout, timeout_msecs, just_this_one)
!      register Lisp_Object process, timeout, timeout_msecs, just_this_one;
  {
    int seconds;
    int useconds;
***************
*** 3776,3782 ****
      XSETFASTINT (process, 0);
  
    return
!     (wait_reading_process_input (seconds, useconds, process, 0)
       ? Qt : Qnil);
  }
  
--- 3779,3787 ----
      XSETFASTINT (process, 0);
  
    return
!     (wait_reading_process_input (seconds, useconds, process,
! 				 NILP (just_this_one) ? 0 :
! 				 !INTEGERP (just_this_one) ? -1 : -2)
       ? Qt : Qnil);
  }
  
***************
*** 4032,4037 ****
--- 4037,4043 ----
    EMACS_TIME timeout, end_time;
    int wait_channel = -1;
    struct Lisp_Process *wait_proc = 0;
+   int just_the_wait_proc = 0;
    int got_some_input = 0;
    /* Either nil or a cons cell, the car of which is of interest and
       may be changed outside of this routine.  */
***************
*** 4048,4053 ****
--- 4054,4064 ----
        wait_proc = XPROCESS (read_kbd);
        wait_channel = XINT (wait_proc->infd);
        XSETFASTINT (read_kbd, 0);
+       if (do_display < 0)
+ 	{
+ 	  just_the_wait_proc = do_display;
+ 	  do_display = 0;
+ 	}
      }
  
    /* If waiting for non-nil in a cell, record where.  */
***************
*** 4122,4128 ****
  	 But not if wait_for_cell; in those cases,
  	 the wait is supposed to be short,
  	 and those callers cannot handle running arbitrary Lisp code here.  */
!       if (NILP (wait_for_cell))
  	{
  	  EMACS_TIME timer_delay;
  
--- 4133,4140 ----
  	 But not if wait_for_cell; in those cases,
  	 the wait is supposed to be short,
  	 and those callers cannot handle running arbitrary Lisp code here.  */
!       if (NILP (wait_for_cell)
! 	  && just_the_wait_proc != -2)
  	{
  	  EMACS_TIME timer_delay;
  
***************
*** 4258,4264 ****
  
        /* Wait till there is something to do */
  
!       if (!NILP (wait_for_cell))
  	{
  	  Available = non_process_wait_mask;
  	  check_connect = check_delay = 0;
--- 4270,4281 ----
  
        /* Wait till there is something to do */
  
!       if (just_the_wait_proc)
! 	{
! 	  FD_SET (wait_channel, &Available);
! 	  check_connect = check_delay = 0;
! 	}
!       else if (!NILP (wait_for_cell))
  	{
  	  Available = non_process_wait_mask;
  	  check_connect = check_delay = 0;


--
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-16 14:37 ` Kim F. Storm
@ 2004-08-17 11:31   ` Milan Zamazal
  2004-08-17 11:38     ` Kim F. Storm
  0 siblings, 1 reply; 10+ messages in thread
From: Milan Zamazal @ 2004-08-17 11:31 UTC (permalink / raw)


>>>>> "KFS" == Kim F Storm <storm@cua.dk> writes:

    KFS> blocking everything including timers isn't very good, but may
    KFS> be acceptable for very short periods of time.

Yes, that's what I need.

    KFS> Here's an (untested) patch that adds a "just-this-one" arg to
    KFS> accept-process-output

Thanks!

Unfortunately, when called as follows:

  (accept-process-output your-process nil nil 1)

Emacs segfaults.  FWIW, the traceback is 

  #0  0x08186fa7 in wait_reading_process_input (time_limit=-1, microsecs=0,
      read_kbd=0, do_display=0) at process.c:4275
  #1  0x08186574 in Faccept_process_output (process=148636188, timeout=0,
      timeout_msecs=138317841, just_this_one=8) at process.c:3781
  #2  0x08154eb8 in Feval (form=138037816) at eval.c:2101
  ...

The problem is that wait_channel is -1 on the segfaulting line:

  FD_SET (wait_channel, &Available);

I don't understand it, since wait_proc->infd is 72 (`pr' says 9) and the
same call without the JUST-THIS-ONE argument

  (accept-process-output your-process nil nil nil)

works fine.

Regards,

Milan Zamazal

-- 
It is the reformer, who is anxious for the reform, and not society, from which
he should expect nothing better than opposition, abhorrence and even mortal
persecution.                                                   -- M. K. Gandhi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-17 11:31   ` Milan Zamazal
@ 2004-08-17 11:38     ` Kim F. Storm
  2004-08-17 20:42       ` Milan Zamazal
  0 siblings, 1 reply; 10+ messages in thread
From: Kim F. Storm @ 2004-08-17 11:38 UTC (permalink / raw)
  Cc: emacs-devel

Milan Zamazal <pdm@brailcom.org> writes:

> The problem is that wait_channel is -1 on the segfaulting line:

Ah, yes, that can happen.

> 
>   FD_SET (wait_channel, &Available);

Try this line instead:

	  FD_SET (XINT (wait_proc->infd), &Available);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-17 11:38     ` Kim F. Storm
@ 2004-08-17 20:42       ` Milan Zamazal
  0 siblings, 0 replies; 10+ messages in thread
From: Milan Zamazal @ 2004-08-17 20:42 UTC (permalink / raw)


>>>>> "KFS" == Kim F Storm <storm@cua.dk> writes:

    >> FD_SET (wait_channel, &Available);

    KFS> Try this line instead:

    KFS> 	  FD_SET (XINT (wait_proc->infd), &Available);

It works well now, thanks!

Regards,

Milan Zamazal

-- 
It is the reformer, who is anxious for the reform, and not society, from which
he should expect nothing better than opposition, abhorrence and even mortal
persecution.                                                   -- M. K. Gandhi

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-16  9:21 Single process output reading Milan Zamazal
  2004-08-16 14:37 ` Kim F. Storm
@ 2004-08-18  1:34 ` Richard Stallman
  2004-08-18 20:50   ` Milan Zamazal
  2004-08-19 11:40   ` Kim F. Storm
  1 sibling, 2 replies; 10+ messages in thread
From: Richard Stallman @ 2004-08-18  1:34 UTC (permalink / raw)
  Cc: emacs-devel

    IMO a better way would be to allow restricting accept-process-output to
    just a single process output reading.  Then the speech output system,
    aware of possible consequences of advising 'message' etc., could invoke
    accept-process-output in the restricted form, without the danger of
    unwanted side effects.

I think it would be reasonable to provide a way to tell
wait_reading_process_output to ignore certain processes and read from
certain other processes.  I worry about the idea of not running timers,
though, and that seems unnecessary for what you need.  I think it
would be better to implement the feature so that timers do run.

I think it would be better to clean up the calling conventions
of wait_reading_process_output rather than try to squeeze everything
into the existing argumemts.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-18  1:34 ` Richard Stallman
@ 2004-08-18 20:50   ` Milan Zamazal
  2004-08-20  4:48     ` Richard Stallman
  2004-08-19 11:40   ` Kim F. Storm
  1 sibling, 1 reply; 10+ messages in thread
From: Milan Zamazal @ 2004-08-18 20:50 UTC (permalink / raw)


>>>>> "RS" == Richard Stallman <rms@gnu.org> writes:

    RS> I worry about the idea of not running timers, though, 

Why?  There are already many ways how to prevent running timers for a
while in Emacs, like running a piece of Elisp code or calling a process
synchronously.  So what's the problem with the special-case
accept-process-output call?

    RS> and that seems unnecessary for what you need.  I think it would
    RS> be better to implement the feature so that timers do run.

I think that would mean that timers should be generally reentrant, as
well as some kinds of speech output functions.

Regards,

Milan Zamazal

-- 
SomeProgrammersLikeWritingLikeThis.IDontThinkThisFormOfCommunicationIs\
AGoodIdea.IApologizeToAllWhoCantReadMyTextsWrittenInATraditionalStyle.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-18  1:34 ` Richard Stallman
  2004-08-18 20:50   ` Milan Zamazal
@ 2004-08-19 11:40   ` Kim F. Storm
  2004-08-20  4:49     ` Richard Stallman
  1 sibling, 1 reply; 10+ messages in thread
From: Kim F. Storm @ 2004-08-19 11:40 UTC (permalink / raw)
  Cc: Milan Zamazal, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     IMO a better way would be to allow restricting accept-process-output to
>     just a single process output reading.  Then the speech output system,
>     aware of possible consequences of advising 'message' etc., could invoke
>     accept-process-output in the restricted form, without the danger of
>     unwanted side effects.
> 
> I think it would be reasonable to provide a way to tell
> wait_reading_process_output to ignore certain processes and read from
> certain other processes.  I worry about the idea of not running timers,
> though, and that seems unnecessary for what you need.  I think it
> would be better to implement the feature so that timers do run.
> 
> I think it would be better to clean up the calling conventions
> of wait_reading_process_output rather than try to squeeze everything
> into the existing argumemts.

I can do that.

Should I rename wait_reading_process_input to wait_reading_process_output ?

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-18 20:50   ` Milan Zamazal
@ 2004-08-20  4:48     ` Richard Stallman
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Stallman @ 2004-08-20  4:48 UTC (permalink / raw)
  Cc: emacs-devel

    Why?  There are already many ways how to prevent running timers for a
    while in Emacs, like running a piece of Elisp code or calling a process
    synchronously.  So what's the problem with the special-case
    accept-process-output call?

I guess you are right.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Single process output reading
  2004-08-19 11:40   ` Kim F. Storm
@ 2004-08-20  4:49     ` Richard Stallman
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Stallman @ 2004-08-20  4:49 UTC (permalink / raw)
  Cc: pdm, emacs-devel

    Should I rename wait_reading_process_input to wait_reading_process_output ?

Indeed, it would be better to make the code consistent in regard
to whether we call this "input" or "output" ;-).

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2004-08-20  4:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-08-16  9:21 Single process output reading Milan Zamazal
2004-08-16 14:37 ` Kim F. Storm
2004-08-17 11:31   ` Milan Zamazal
2004-08-17 11:38     ` Kim F. Storm
2004-08-17 20:42       ` Milan Zamazal
2004-08-18  1:34 ` Richard Stallman
2004-08-18 20:50   ` Milan Zamazal
2004-08-20  4:48     ` Richard Stallman
2004-08-19 11:40   ` Kim F. Storm
2004-08-20  4:49     ` Richard Stallman

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).