JoshCheek / seeing_is_believing

Displays the results of every line of code in your file
1.3k stars 54 forks source link

exec error: Timeout Error after 12.0 seconds! #71

Closed KINGSABRI closed 8 years ago

KINGSABRI commented 8 years ago

Hi I'm trying to get a function result but I'm getiing 'exec error: Timeout Error after 12.0 seconds!' error.

This is working well with small code like ([*1..10]) but not in a bigger scale (eg. optparse)

JoshCheek commented 8 years ago

Can you post an example? Generally, the editor integrations work by running the code and then updating the editor. If there is anything making the code run a long time (blocking like gets, infinite loop, massive amounts of inspected data, like a giant loop or a big object geaph) then you could hit the timeout. You can increase the timeout, even turn it off, or write it to not record so much data (there are also flags to restrict amt of data recorded, to avoid this). Generally, I don't know the issue / solution without seeing the code.

On Friday, July 8, 2016, KING SABRI notifications@github.com wrote:

Hi I'm trying to get a function result but I'm getiing 'exec error: Timeout Error after 12.0 seconds!' error.

This is working well with small code like ([*1..10]) but not in a bigger scan

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/JoshCheek/seeing_is_believing/issues/71, or mute the thread https://github.com/notifications/unsubscribe/AAEut07BUXj-Zgwr9adkAWRrDBmJsTHmks5qTvIWgaJpZM4JIgTI .

JoshCheek commented 8 years ago

The issue

I'm assuming you're using it with ftpd while working on this commit.

If so, you would hit the issue because SiB will run that file directly, which will run the server (line 288), which has an infinite loop (line 212).

Two solutions

How do you get around that? I independently think it would be best to put FTPDrb::Arguments in its own file (this would enable you to require it, which could be valuable for testing, or if you wanted to subclass it or something), which could then be run by adding a line at the bottom of the file to invoke it. This has the advantage that you can run SiB on the parsing code itself, which gives you insight into what's happening within the blocks, for example.

However, a simple enough way to use SiB with it as it stands is to load the file (can't require since it doesn't end in a valid ruby extension). At that point $0 won't match __FILE__, so it won't start the server. For example, I did this just now (note that I ran it with the --xmpfilter-style flag, which will inspect a line in a more helpful way if you explicitly annotate an annotation to the line after it).

load '/Users/josh/deleteme/ftpd/bin/ftpdrb'

FTPDrb::Arguments.new(%w[--tls explicit --read-only --auth user -d])
# => #<FTPDrb::Arguments:0x007f93711f14c0
#     @account="",
#     @auth_level=:user,
#     @debug=true,
#     @interface="127.0.0.1",
#     @log=nil,
#     @nat_ip=nil,
#     @passive_ports=nil,
#     @password="",
#     @path=nil,
#     @port=0,
#     @read_only=true,
#     @servername="FTPd - Pure Ruby FTP server",
#     @session_timeout=300,
#     @tls=:explicit,
#     @user="josh">

Better than either solution

The reality is, though, that the most effective way to use SiB is to try out ideas that have been decoupled from their context, not to run entire programs. For example, say you were working on the --port option, and wanted to figure out the how to tell OptionParser to make the argument an integer. It's not very effective feedback to try to do that within the context of the whole program. Instead, jump over to SiB and make a minimal example, trying things out and editing as you go. Once you get it figured out there, you know what to do for the real argument parser, I even advocate pasting the solution right into it and editing it to work in context. The SiB experimentation to get it figured out might look something like this:

require 'optparse'

def parse(*args)
  value = :none
  OptionParser.new do |op|
    op.on('-p', '--port N', Integer, 'desc') { |p| value = p }
  end.parse(args)
  args  # => [], ["-p", "1"], ["--port", "2"], ["--port=3"], ["-p", "6", "-p", "7"], ["-p9"]
  value # => :none, 1, 2, 3, 7, 9
end

parse                               # => :none
parse '-p', '1'                     # => 1
parse '--port', '2'                 # => 2
parse '--port=3'                    # => 3
parse '--port 4'          rescue $! # => #<OptionParser::InvalidOption: --port 4>
parse '--port', '=', '5'  rescue $! # => #<OptionParser::InvalidArgument: --port =>
parse '-p'                rescue $! # => #<OptionParser::MissingArgument: -p>
parse '-p', '6', '-p', '7'          # => 7
parse '-p', '-p', '8'     rescue $! # => #<OptionParser::InvalidArgument: -p -p>
parse '-p9'                         # => 9
parse '-p', '10.11'       rescue $! # => #<OptionParser::InvalidArgument: -p 10.11>

Note how much easier it is to experiment and iterate in this context than in the real one, so use SiB as a lab to run experiments, and then just take the conclusions back.

Thoughts on the code

Since I glanced through bin/ftpdrb, here's a few thoughts: