What does number mean in the backtrace? - ruby

Does the 1, 2, 3, 4, 5, 1, 2 indicates these two errors (EOFError and NoMethodError) happened in different threads?
Traceback (most recent call last):
2: from /gem/lib/my/project/conn.rb:72:in `block in initialize'
1: from /usr/local/lib/ruby/2.7.0/openssl/buffering.rb:125:in `readpartial'
/usr/local/lib/ruby/2.7.0/openssl/buffering.rb:125:in `sysread': end of file reached (EOFError)
5: from /gem/lib/my/project/conn.rb:69:in `block in initialize'
4: from /gem/lib/my/project/conn.rb:80:in `rescue in block in initialize'
3: from /gem/lib/my/project/session.rb:60:in `disconnected'
2: from /gem/lib/my/project/session.rb:217:in `retransmit'
1: from /gem/lib/my/project/session.rb:117:in `transmit_results'
/gem/lib/rspec/buildkite/analytics/conn.rb:104:in `transmit': undefined method `write' for nil:NilClass (NoMethodError)

The numbers correspond to the position of the stack frame in the execution stack and thus in the quoted backtrace.
In your question, you are quoting two different exceptions with their respective back traces. By going up the back trace (thus by going from the bottom of the trace towards the top, you can trace the respective calls and their line numbers in their source file. Upper traces (i.e. those with a larger number) have called functionality with lower numbers.
Note that different Ruby versions use a different default order of those traces. Older versions have but the inner calls (i.e. lower numbers) on top of the trace. Since Ruby 2.5, the default order was reversed to show th exception and the inner calls at the bottom.

Related

Elisp, calling with progn yields different result than calling individually

In Emacs (with C-:), those 2 calls yield different results :
(progn (run-python (python-shell-parse-command) nil nil) (python-shell-send-buffer))
and
(run-python (python-shell-parse-command) nil nil)
# then, in another C-:
(python-shell-send-buffer)
In the first call, I get a python shell with the following error:
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name '__PYTHON_EL_eval' is not defined
Why is the result different for these 2 elisp codes? I am trying to put these commands in a function, but I cannot if they yield an error together.
As suggested by #Lindydancer, run-python selects the comint buffer, so python-shell-send-buffer will be called with that as the current buffer, which probably isn't what you intended.
See also C-hf save-current-buffer
Also note that the inferior process is started asynchronously, so run-python might return before the process is ready to receive input. You may or may not have to take that into account.
In general there is no reason to expect running two things in immediate sequence via progn to produce the same results as two completely independent calls to each of those things, separated by not only time but also by trips through the Emacs command loop, with all of the intervening executed code which that entails.

Memory leak in ruby

I have such code in irb:
2.6.3 :001 > a = []; 100000000000.times do a.push([1]) end
^CTraceback (most recent call last):
3: from (irb):1
2: from (irb):1:in `times'
1: from (irb):1:in `block in irb_binding'
IRB::Abort (abort then interrupt!)
2.6.3 :002 > a.clear
=> []
2.6.3 :003 > GC.start
=> nil
2.6.3 :004 > a.size
=> 0
2.6.3 :005 > exit
My memory chart:
So memory is completely released only at the exit.
How memory can freed completely before app exit?
Operating as Designed
It's a leak if and only if the memory isn't returned to the system after Ruby exits. Since that's not the behavior you're describing, it's fair to say that your interpreter appears to be operating as designed.
See below for a little more about how Ruby's garbage collection works at a high level, and why your array-building is so memory intensive.
No Memory is Leaking
This is not a leak; this is how Ruby garbage collection works! It's basically a mark-and-sweep garbage collector, with some new support for compaction. At a high level, Ruby allocates memory for objects still in scope, and generally won't release the allocation until all references go out of scope.
Ruby's garbage collection isn't well-documented outside of source code, and the implementation is a bit more complex than what I described above. Furthermore, the garbage collection implementation can vary from release to release, and between different interpreters (e.g. JRuby and MRI) too! Still, it's sufficient to understand what you're seeing.
Basically, 100000000000.times do a.push([1]) end will push an element onto Array a 100 million times. As long as a is in scope, the memory won't be garbage collected. Even if you manually start the garbage collector routines after a goes out of scope, Ruby may or may not free the memory if the system isn't under memory pressure.
I wouldn't worry about this unless you have very long-lived processes that need to keep millions of records in active memory. If you do, a purpose-built cache or database (e.g. memcached, Redis) might be more efficient.

Debugger implementation - Step over issue

I am currently writing a debugger for a script virtual machine.
The compiler for the scripts generates debug information, such as function entry points, variable scopes, names, instruction to line mappings, etc.
However, and have run into an issue with step-over.
Right now, I have the following:
1. Look up the current IP
2. Get the source line from that
3. Get the next (valid) source line
4. Get the IP where the next valid source line starts
5. Set a temporary breakpoint at that instruction
or: if the next source line no longer belongs to the same function, set the temp breakpoint at the next valid source line after return address.
So far this works well. However, I seem to be having problems with jumps.
For example, take the following code:
n = 5; // Line A
if(n == 5) // Line B
{
foo(); // Line C
}
else
{
bar(); // Line D
--n;
}
Given this code, if I'm on line B and choose to step-over, the IP determined for the breakpoint will be on line C. If, however, the conditional jump evaluates to false, it should be placed on line D. Because of this, the step-over wouldn't halt at the expected location (or rather, it wouldn't halt at all).
There seems to be little information on debugger implementation of this specific issue out there. However, I found this. While this is for a native debugger on Windows, the theory still holds true.
It seems though that the author has not considered this issue, either, in section "Implementing Step-Over" as he says:
1. The UI-threads calls CDebuggerCore::ResumeDebugging with EResumeFlag set to StepOver.
This tells the debugger thread (having the debugger-loop) to put IBP on next line.
2. The debugger-thread locates next executable line and address (0x41141e), it places an IBP on that location.
3. It calls then ContinueDebugEvent, which tells the OS to continue running debuggee.
4. The BP is now hit, it passes through EXCEPTION_BREAKPOINT and reaches at EXCEPTION_SINGLE_STEP. Both these steps are same, including instruction reversal, EIP reduction etc.
5. It again calls HaltDebugging, which in turn, awaits user input.
Again:
The debugger-thread locates next executable line and address (0x41141e), it places an IBP on that location.
This statement does not seem to hold true in cases where jumps are involved, though.
Has anyone encountered this problem before? If so, do you have any tips on how to tackle this?
Since this thread comes in Google first when searching for "debugger implement step over". I'll share my experiences regarding the x86 architecture.
You start first by implementing step into: This is basically single stepping on the instructions and checking whether the line corresponding to the current EIP changes. (You use either the DIA SDK or the read the dwarf debug data to find out the current line for an EIP).
In the case of step over: before single stepping to the next instruction, you'll need to check if the current instruction is a CALL instuction. If it's a CALL instruction then put a temporary breakpoint on the instruction following it and continue execution till the execution stops (then remove it). In this case you effectively stepped over function calls literally in the assembly level and so in the source too.
No need to manage stack frames (unless you'll need to deal with single line recursive functions). This analogy can be applied to other architectures as well.
Ok, so since this seems to be a bit of black magic, in this particular case the most intelligent thing was to enumerate the instruction where the next line starts (or the instruction stream ends + 1), and then run that many instructions before halting again.
The only gotcha was that I have to keep track of the stack frame in case CALL is executed; those instructions should run without counting in case of step-over.

Ruby + Windows + Timeouts + SerialPorts won't work

I am developing a multiplatform Ruby program that is supposed to connect via USB to a serial device.
First I was using the serialport gem (1.0.4), but then I ran into some strange problems and had to drop it.
I then proceeded to communicate via Ruby's IO class, as follows:
#port = IO.new IO.sysopen(path, mode), mode
Communication via syswrite and sysread is perfect both in Linux as Windows.
With the communication done, I tried setting up timeouts so that the program won't hang if any desync occurs. All done on the Linux side with timeout.rb, but Windows won't get me control of the interpreter again after calling any IO read method (sysread, getc, gets, getbyte... I tried them all!).
I experimented with Terminator, but it wouldn't even run, throwing argument exceptions instead of timing out -- even in Linux!:
require 'terminator'
Terminator.terminate 2 do
sleep 4
end
produces:
/var/lib/gems/1.9.1/gems/terminator-0.4.4/lib/terminator.rb:164: Use RbConfig instead of obsolete and deprecated Config.
ArgumentError: wrong number of arguments (1 for 0)
from /var/lib/gems/1.9.1/gems/terminator-0.4.4/lib/terminator.rb:127:in `block in terminate'
from (irb):12:in `call'
from (irb):12:in `sleep'
from (irb):12:in `block in irb_binding'
from /var/lib/gems/1.9.1/gems/terminator-0.4.4/lib/terminator.rb:134:in `call'
from /var/lib/gems/1.9.1/gems/terminator-0.4.4/lib/terminator.rb:134:in `terminate'
from (irb):11
from /usr/bin/irb:12:in `<main>'
As SystemTimer relies on UNIX signals and doesn't work on Windows (it simply wraps timeout.rb), I am stuck with a multiplatform program that would just eternally hang when running on Windows, although just fine on Linux.
Is there any way I could set timeouts on serial port reading on Windows? Perhaps a win32api call?
Thank you for your time. :)
Edit:
I believe I found a way around the problem, although it really stinks.
instead of
Timeout::timeout 0.5 do
gets
end
I tried
begin
Timeout::timeout 0.5 do
Thread.new do
gets
end.join
end
rescue
"Expired :)"
end
and it seems to be fine on IRB.
I'm going to implement and test it and then I'll post the results here. :)
However, any prettier solution is most than welcome!

Do Ruby objects have a size limit?

I'm building some large strings which have a short lifetime within the application. Will the String objects grow arbitrarily large up to the physical limits of the ruby instance?
What I'm wondering is if, without any intervention in limiting the string size, my application would get hosed by running out of memory, or whether it would degrade gracefully.
Thanks for any input!
There is a limit. A String can be 2**31 - 1 (and accordingly 2**63 - 1 on 64 bit ruby). You can see the limit with:
>> s = String.new("1" * (2**32))
RangeError: bignum too big to convert into `long'
from (irb):3:in `*'
from (irb):3
>> s = String.new("1" * (2**31))
RangeError: bignum too big to convert into `long'
from (irb):4:in `*'
from (irb):4
Having said that, while you could try to allocate a string that big it will likely fail (at least on a 32 bit system as typically the maximum amount of memory a process can allocate is between 2.5 and 3GB and a 2**31 - 1 length string is nearly 2GB by itself.) As seen:
>> "1" * (2**30)
NoMemoryError: failed to allocate memory
from /usr/lib/ruby/1.8/irb.rb:310:in `inspect'
from /usr/lib/ruby/1.8/irb.rb:310:in `output_value'
from /usr/lib/ruby/1.8/irb.rb:159:in `eval_input'
from /usr/lib/ruby/1.8/irb.rb:271:in `signal_status'
from /usr/lib/ruby/1.8/irb.rb:155:in `eval_input'
from /usr/lib/ruby/1.8/irb/ruby-lex.rb:244:in `each_top_level_statement'
from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `loop'
from /usr/lib/ruby/1.8/irb/ruby-lex.rb:230:in `each_top_level_statement'
from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `catch'
from /usr/lib/ruby/1.8/irb/ruby-lex.rb:229:in `each_top_level_statement'
from /usr/lib/ruby/1.8/irb.rb:154:in `eval_input'
from /usr/lib/ruby/1.8/irb.rb:71:in `start'
from /usr/lib/ruby/1.8/irb.rb:70:in `catch'
from /usr/lib/ruby/1.8/irb.rb:70:in `start'
from /usr/bin/irb:13
Maybe IRB bug!!
I don't believe there is any way to catch the NoMemoryError.
Updated to reflect the comment from sepp2k

Resources