Check Why Ruby Script Hangs

Ruby script hangs forever

You cannot use while loop with upto.

Change it to:

0.upto ARGV[0].to_i do
num << rand(254)
end

And it works properly (I've changed braces to curly one, because I believe you want 254 to be parameter here).


Sidenote:

Remember when writing threads program in Ruby, that CRuby has GIL - Global Interpreter Lock. Therefore only one thread will be operating at one time. If you want different behaviour - switch for example to jRuby. More information about GIL can be found f.e. here: http://www.jstorimer.com/blogs/workingwithcode/8085491-nobody-understands-the-gil

A Simple Ruby Script Freezes My Machine

You are creating a huge array which you don't even need. That is forcing your machine to start paging (it would take up 5% of the 64-bit address space and your machine certainly doesn't have that much RAM). Your code is not making it to the loop (the condition in the if statement isn't valid ruby).

CONSTANT = 1000 
# start with something small, then increase by 10
# 10000000 works for me.

start = Time.now
CONSTANT.times do |i|
if 1000 < i && CONSTANT * 9 / 10

elsif i > CONSTANT * 9 / 10

else

end
end
finish = Time.now

puts "Running time: #{finish - start} seconds"

How to find out why rails server hangs at 100%?

Once you have attached with gdb to the busy looping process then call rb_backtrace from gdb:

> call rb_backtrace()

The output from rb_backtrace will be similar to a crash report, and the output will go to your log files similar to a standard Ruby error backtrace.

From there you should hopefully already be a step closer to the solution since you will see where in your Ruby code the process is stuck.

You can check out some more tips here:

http://isotope11.com/blog/getting-a-ruby-backtrace-from-gnu-debugger

How to debug Ruby scripts

Use Pry (GitHub).

Install via:

$ gem install pry
$ pry

Then add:

require 'pry'; binding.pry

into your program.

As of pry 0.12.2 however, there are no navigation commands such as next, break, etc. Some other gems additionally provide this, see for example pry-byebug.

Ruby File IO Hang

Ok..since running the test code does not require any external ruby libraries I can compile 1.9 on my machine without installing it, and run the test program.

Here's what I see:

  1. Ruby seems to "hang" (you can't interrupt it, and it doesn't exit by itself).
  2. top shows ruby running at 100% CPU
  3. strace shows no output once it goes into 100% CPU mode.

From this it's obvious Ruby goes into an infinite loop. And looking at each_byte in io.c, and adding a printf into the suspicious location reveals where we get stuck:

static VALUE
rb_io_each_byte(VALUE io)
{
rb_io_t *fptr;
char *p, *e;

RETURN_ENUMERATOR(io, 0, 0);
GetOpenFile(io, fptr);

for (;;) {
p = fptr->rbuf+fptr->rbuf_off;
e = p + fptr->rbuf_len;

printf("UH OH: %d < %d\n", p, e); /* INFINITE LOOP ALERT */

while (p < e) {
fptr->rbuf_off++;
fptr->rbuf_len--;
rb_yield(INT2FIX(*p & 0xff));
p++;
errno = 0;
}
rb_io_check_byte_readable(fptr);
READ_CHECK(fptr);
if (io_fillbuf(fptr) < 0) {
break;
}
}
return io;
}

On my machine it prints this:

UH OH: 0 < 0
UH OH: 137343104 < 137351296
UH OH: 137343119 < 137343104
UH OH: 137343119 < 137343104
UH OH: 137343119 < 137343104
...ad infinitum...

And 137343119 is NOT less than 137343104, which means we stop going into the while loop (which would yield the block).

When you run the code so that it doesn't hang you get this:

UH OH: 0 < 0
UH OH: 137341560 < 137349752
UH OH: 137341560 < 137349752
UH OH: 137341560 < 137349752
UH OH: 137341560 < 137349752
....

And 137341560 IS less than 137349752.

Anyway..that's all I got for now. Still no clue why it's happening. But now we at least know WHAT is happening. Someone who wrote that code could probably explain why it's happening immidiately.

Anyway..I still think the lseek calls somehow mess up ruby's internal file pointers, and the above loop goes haywire because of that.

EDIT

And here's a fix:

Change flush_before_seek in io.c to look like this:

static rb_io_t *
flush_before_seek(rb_io_t *fptr)
{
int wbuf_len = fptr->wbuf_len;

if (io_fflush(fptr) < 0)
rb_sys_fail(0);

if (wbuf_len != 0)
io_unread(fptr);

errno = 0;
return fptr;
}

What I added was the check for wbuf_len != 0, so that we don't do io_unread unnecessarily. Calling io_unread while in the each_byte loop is what messes things up. Skipping the unread makes things work and all the tests for make test still pass.

Anyway..it's not a proper fix, since there is some fundamental thought mistake with f.pos. It's just a workaround...but it fixes the above problem none the less :-/

Ruby run external program stops script

Try to run Something.exe in a new Thread:

Thread.new { system("Something.exe") }



Related Topics



Leave a reply



Submit