Ruby + linux /proc/acpi deadlock?

Hi Rubyists,

I'm working on a predictive battery monitor in Ruby. One issue I've
found is that when I read /proc/acpi/battery/BAT1/state and there are
other Ruby threads running, the read seems to freeze. This doesn't
happen with other files in /proc/acpi (that I've tried, at least) and
doesn't happen if there's no threading going on.

Here's some code that hangs on the read for me:

PROC_FILE = "/proc/acpi/battery/BAT1/state" # freezes
#PROC_FILE = "/proc/acpi/power_resource/PFAN/state" # doesn't freeze
FREEZE = true # when this is true, the "read" thread freezes for me

def read
  puts "=== starting to read at #{Time.now}"
  IO.foreach(PROC_FILE) { |l| puts "> #{l}" }
  puts "=== done reading at #{Time.now}"
end

Thread.new do
  while true
    puts "zzz..."
    sleep 1
  end
end if FREEZE

while true
  read
  sleep 1
end

This might be some weird kernel interaction thing that's specific to my
buggy BIOS, but I thought I'd check and see if others experienced the
same behavior.

Thanks,

···

--
William <wmorgan-ruby-talk@masanjin.net>

Hi Rubyists,

I'm working on a predictive battery monitor in Ruby. One issue I've
found is that when I read /proc/acpi/battery/BAT1/state and there are
other Ruby threads running, the read seems to freeze. This doesn't
happen with other files in /proc/acpi (that I've tried, at least) and
doesn't happen if there's no threading going on.

Here's some code that hangs on the read for me:

PROC_FILE = "/proc/acpi/battery/BAT1/state" # freezes
#PROC_FILE = "/proc/acpi/power_resource/PFAN/state" # doesn't freeze

I have the same beavior with these files:
PROC_FILE = "/proc/acpi/battery/BAT0/state" # freezes
PROC_FILE = "/proc/acpi/power_resource/PRCF/state" # doesn't freeze

I can't explain it :slight_smile:

···

On Wed, Aug 18, 2004 at 09:23:55PM +0900, William Morgan wrote:

FREEZE = true # when this is true, the "read" thread freezes for me

def read
  puts "=== starting to read at #{Time.now}"
  IO.foreach(PROC_FILE) { |l| puts "> #{l}" }
  puts "=== done reading at #{Time.now}"
end

Thread.new do
  while true
    puts "zzz..."
    sleep 1
  end
end if FREEZE

while true
  read
  sleep 1
end

This might be some weird kernel interaction thing that's specific to my
buggy BIOS, but I thought I'd check and see if others experienced the
same behavior.

Thanks,

--
William <wmorgan-ruby-talk@masanjin.net>

back when I was starting in Ruby one of the first small tries was...
(fix code first, terminal is eating some chars)

run with no window decoration
not very pretty, but does the job till today :slight_smile:

Martin

···

William Morgan <wmorgan-ruby-talk@masanjin.net> wrote:

I'm working on a predictive battery monitor in Ruby.

--------------------------------------------------------------------------

$stdout.sync = true

def resize (w,h) # resize terminal
  printf("\033[8;#{h};#{w}t")
end

def readme
  r1 = IO.readlines("/proc/acpi/battery/BAT1/state").grep(/remaining/)
  r1 = /\s*(\d*)\smWh/.match(r1[0])[1].to_s if r1.size == 1
  return r1
end

resize (10,1)

r = IO.readlines("/proc/acpi/battery/BAT1/state")
if /present.+no/ === r[0] then
printf("\n no batt ")
sleep 3
exit 1
end

or1 = readme
printf("\n%s 000",or1.rjust(5).tr(" ","0"))
nr1 = readme

loop do
  nr1 = readme
  if (nr1 != or1)
    if or1.to_i <3000 then
      'xgamma -gamma 0.3' # <---- fix me!
      sleep 0.3
      'xgamma -gamma 1.0' # <---- fix me!
    end
    printf("\n%s %s",nr1.rjust(5).tr(" ","0"),(or1.to_i-nr1.to_i).to_s.rjust(3).tr(" ","0"))
    or1 = nr1
  end
  sleep 15
end

Excerpts (reformatted) from Roeland Moors's mail of 20 Aug 2004 (EDT):

> Here's some code that hangs on the read for me:
>
> PROC_FILE = "/proc/acpi/battery/BAT1/state" # freezes
> #PROC_FILE = "/proc/acpi/power_resource/PFAN/state" # doesn't freeze

I have the same beavior with these files:
PROC_FILE = "/proc/acpi/battery/BAT0/state" # freezes
PROC_FILE = "/proc/acpi/power_resource/PRCF/state" # doesn't freeze

I can't explain it :slight_smile:

So, guys, is this a bug in Ruby, or what?

(details: ruby 1.8.1 (2004-02-03) [i386-linux] and Linux kernel 2.6.8.1)

···

--
William <wmorgan-ruby-talk@masanjin.net>

Excerpts (reformatted) from Martin Pirker's mail of 23 Aug 2004 (EDT):

back when I was starting in Ruby one of the first small tries was...
(fix code first, terminal is eating some chars)

Check out http://tdbatmon.rubyforge.org and you can see what I've done.
It turns out my particular battery is pretty linear so all my
fancy-pants prediction is wasted, but it's still kinda cool, IMO.

···

--
William <wmorgan-ruby-talk@masanjin.net>

I also have the problem with these files:
PROC_FILE = "/proc/acpi/fan/CFAN/state" # freezes
PROC_FILE = "/proc/acpi/ac_adapter/ACAD/state" # doesn't freezes

My system:
- Linux laptop 2.6.6 #1 Wed Jul 7 20:20:50 CEST 2004 i686 GNU/Linux
- ruby 1.8.2 (2004-07-29) [i386-linux]
- Asus L3C
- Debian testing

···

On Tue, Aug 24, 2004 at 05:12:05AM +0900, William Morgan wrote:

Excerpts (reformatted) from Roeland Moors's mail of 20 Aug 2004 (EDT):
> > Here's some code that hangs on the read for me:
> >
> > PROC_FILE = "/proc/acpi/battery/BAT1/state" # freezes
> > #PROC_FILE = "/proc/acpi/power_resource/PFAN/state" # doesn't freeze
>
> I have the same behavior with these files:
> PROC_FILE = "/proc/acpi/battery/BAT0/state" # freezes
> PROC_FILE = "/proc/acpi/power_resource/PRCF/state" # doesn't freeze
>
> I can't explain it :frowning:

So, guys, is this a bug in Ruby, or what?

(details: ruby 1.8.1 (2004-02-03) [i386-linux] and Linux kernel 2.6.8.1)

--
Roeland

Excerpts (reformatted) from Roeland Moors's mail of 23 Aug 2004 (EDT):

I also have the problem with these files:
PROC_FILE = "/proc/acpi/fan/CFAN/state" # freezes
PROC_FILE = "/proc/acpi/ac_adapter/ACAD/state" # doesn't freezes

My system:
- Linux laptop 2.6.6 #1 Wed Jul 7 20:20:50 CEST 2004 i686 GNU/Linux
- ruby 1.8.2 (2004-07-29) [i386-linux]
- Asus L3C
- Debian testing

The issue persists with Ruby 1.8.2 preview 2 on my i686 machine with
kernel 2.6.8.1, so I suggest this is a real-life bug.

Is there a better way of reporting it than just announcing it here?

···

--
William <wmorgan-ruby-talk@masanjin.net>

Hi,

At Fri, 27 Aug 2004 08:40:47 +0900,
William Morgan wrote in [ruby-talk:110600]:

The issue persists with Ruby 1.8.2 preview 2 on my i686 machine with
kernel 2.6.8.1, so I suggest this is a real-life bug.

Is there a better way of reporting it than just announcing it here?

Maybe, strace log?

···

--
Nobu Nakada

Excerpts (reformatted) from Nobuyoshi Nakada's mail of 26 Aug 2004 (EDT):

Maybe, strace log?

Under Ruby 1.8.2 with kernel 2.6.8.1, with this code:

  PROC_FILE = "/proc/acpi/battery/BAT1/state"
  Thread.new { sleep 1000 }
  puts "=== starting to read at #{Time.now}"
  IO.foreach(PROC_FILE) { }
  puts "=== done reading at #{Time.now}"

I get the following strace output:

  [...]
  write(1, "=== starting to read at Fri Aug "..., 53=== starting to read at Fri Aug 27 10:26:58 EDT 2004
  ) = 53
  sigprocmask(SIG_BLOCK, NULL, []) = 0
  open("/proc/acpi/battery/BAT1/state", O_RDONLY|O_LARGEFILE) = 3
  sigprocmask(SIG_BLOCK, NULL, []) = 0
  gettimeofday({1093616818, 153673}, NULL) = 0
  select(4, [3], [], [], {999, 998330}

and it just hangs on that select. If I remove the Thread.new call, I get
this strace output:

  [...]
  open("/proc/acpi/battery/BAT1/state", O_RDONLY|O_LARGEFILE) = 3
  sigprocmask(SIG_BLOCK, NULL, []) = 0
  fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
  mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x402b7000
  read(3, "present: yes\ncap"..., 1024) = 188
  read(3, "", 1024) = 0
  close(3) = 0
  munmap(0x402b7000, 4096) = 0
  gettimeofday({1093616966, 205006}, NULL) = 0
  write(1, "=== done reading at Fri Aug "..., 53=== done reading at Fri Aug 27 10:29:26 EDT 2004
  ) = 53

If I change the filename to /proc/acpi/power_resource/PFAN/state in the
code with threads, select() is used, but it doesn't block.

So it seems like select() on reading particular files in /proc will
block. I guess the question is, is this a kernel bug or a kernel
feature?

···

--
William <wmorgan-ruby-talk@masanjin.net>

Hi,

At Fri, 27 Aug 2004 23:52:08 +0900,
William Morgan wrote in [ruby-talk:110651]:

So it seems like select() on reading particular files in /proc will
block. I guess the question is, is this a kernel bug or a kernel
feature?

Though I'm not a developer of the kernel, it sounds like a bug.

···

--
Nobu Nakada