eregontp / gmail.com wrote:
> normalperson (Eric Wong) wrote:
> > eregontp / gmail.com wrote:
> >  > Something else, I would consider Timeout to be fundamentally
> >  > flawed as long as it relies on Thread#raise, because it can
> >  > fire in the middle of an ensure block:
> >  > http://headius.blogspot.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html
> >  
> >  We have Thread.handle_interrupt, nowadays, to control when
> >  interrupts fire.

> Right, although it's very difficult to use correctly (for
> instance, it's incorrect to use Thread.handle_interrupt inside
> the ensure block) and can easily cause hangs or deadlocks.

Agreed, it should be easier-to-use; but that's a separate issue
and I'm trying to avoid dealing with public API design as much
as possible for this.

> BTW, it looks like MonitorMixin::ConditionVariable doesn't use
> Thread.handle_interrupt and could continue out of #wait (with
> an exception thrown by Thread#raise) without reacquiring the
> lock.

Can you report separately to shugo to be sure he sees it?
I've never really understood the point of that module :x

> It might be nice to have a Timeout variant that only
> interrupts blocking IO, without relying on Thread#raise (but
> just SIGVTALRM).  I think that would be easier/safer to use
> than the current Timeout.timeout().  Not sure how to deal if
> there are multiple IO calls inside that Timeout block though.
> And there could still be blocking IO in an ensure block, which
> would not work as intended.

Agreed, I would welcome a "soft" timeout, without using
signals/raise at all.  I think my work-in-progress "intrusive"
[PATCH 2/1] for this will make such a thing easier-to-implement:

  https://80x24.org/spew/20180622215745.20698-1-e / 80x24.org/raw

> > I considered that, too, but we'd need to add timeouts to
> > every
> single method which can block. There are many: File.open,
> Queue#pop, SizedQueue#push, Mutex#lock/synchronize,
> Process.wait*, IO#gets, IO#write, IO#read, IO#getc,
> IO.copy_stream, ...
> 
> It seems fine to me. Other implementations already have a
> timeout on Queue#pop IIRC.  I'm not sure we need all of them
> right now (what use case for Mutex#lock/synchronize ?).  I
> think the main need would be for standard IO like
> IO#read/write, especially on sockets and pipes.

The maintenance overhead for adding timeouts to every call would
be overwhelming on a human level, especially when 3rd-party
libraries need to be considered.

I would much rather do the following:

	Timeout.timeout(30) do
	  foo.read(...)
	  foo.write(...)
	  IO.copy_stream(...)
	  foo.write(...)
		szqueue.push(...)
		resultq.pop
  end

Than this:

  def now
	  Process.clock_gettime(Process::CLOCK_MONOTONIC)
	end

  begin
		@stop = now + 30
		...
		tout = @stop - now
		raise Timeout::Error if tout <= 0
		foo.read(..., tout)

		tout = @stop - now
		raise Timeout::Error if tout <= 0
		foo.write(..., tout)

		tout = @stop - now
		raise Timeout::Error if tout <= 0
		IO.copy_stream(..., tout)

		tout = @stop - now
		raise Timeout::Error if tout <= 0
		foo.write(..., tout)

		tout = @stop - now
		raise Timeout::Error if tout <= 0
		szqueue.push(..., tout)

		tout = @stop - now
		raise Timeout::Error if tout <= 0
		resultq.pop(tout)
	end

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>