Blocking Problem

Z

Zachary P. Landau

--+QahgC5+KEYLbs62
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline


Hello,

I'm having trouble with IO blocking when reading from a device. It may
be hard for people to help since most people won't be able to test this
themselves, but I'll give it a shot.

I'm trying to read from the CueCat Linux driver, which sits in
/dev/scanner/cuecat. It is sort of like a pipe, you can use File.read
and it outputs a line with a barcode (and some other information).

The problem is, I can't avoid blocking. There is a GTK application, and
then a separate thread that tries to read barcodes and whenever it finds
one, it tells the GTK app.

So my code looks like this:

Thread.new do
File.open(CUECAT_DEV, File::RDONLY | File::NONBLOCK) do |cuecat|
loop do
id, barcode_type, barcode = cuecat.gets.split(/,/)
# do stuff with the barcode
end
end
end

When I use a named pipe instead of CUECAT_DEV, it doesn't block. But
when I use the actual /dev/scanner/cuecat, it blocks. Unfortunately,
blocking locks up the entire application.

I tried getting around the issue by using Gtk.timeout_add instead, but
that didn't help.

The mailing list has some posts about blocking problems, but they are
related to sockets and pipes. As I mentioned earlier, the above code
works when CUECAT_DEV is a pipe.

--
Zachary P. Landau <[email protected]>
GPG: gpg --recv-key 0x24E5AD99 | http://kapheine.hypa.net/kapheine.asc

--+QahgC5+KEYLbs62
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBMQcfCwWyMCTlrZkRAutAAJ9Mqvz/L6eknUCAHzgqG09EqZBbJwCfR81Y
CPQJPCFqkc8T80asv3AJ2IU=
=6cbY
-----END PGP SIGNATURE-----

--+QahgC5+KEYLbs62--
 
R

Robert Klemme

Hm,

did you try to leave out *all* flags on File#open? Also, I'd check whether
maybe the driver has a problem with non blocking IO. Also, sysread might be
an option worth trying. That's all that comes to mind at the moment...

Kind regards

robert
 
K

Kristof Bastiaensen

On Sun, 29 Aug 2004 07:28:59 +0900, Zachary P. Landau wrote:

Hi,

Since you are using Gtk, maybe the Gdk::Input.add method
could help you. You can invoke it like this:

Gdk::Input.add(my_io.to_i, Gdk::Input::Condition::READ) do
#block to execute when data is ready in the io
end

This is the version for gtk2, the gtk (1.2) version is a
little different.
You must have a Gtk.main loop for this to work.
I hope this is helpful.

Regards,
KB
 
Z

Zachary P. Landau

--oLBj+sq0vYjzfsbl
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Hm,
=20
did you try to leave out *all* flags on File#open? Also, I'd check wheth= er
maybe the driver has a problem with non blocking IO. Also, sysread might= be
an option worth trying. That's all that comes to mind at the moment...

No luck with leaving out the flags on File#open, nor sysread. Maybe you
are right about the driver having problems with non blocking IO,
although I don't really know how to test it. Thanks for the ideas,
though.

--
Zachary P. Landau <[email protected]>
GPG: gpg --recv-key 0x24E5AD99 | http://kapheine.hypa.net/kapheine.asc

--oLBj+sq0vYjzfsbl
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBMoCuCwWyMCTlrZkRAjfrAJwMoNgEHWdzrcc3W07niiDv0Jf+EQCeNMS0
BjizbTU1qNJDtOdjLL6awbo=
=pLBi
-----END PGP SIGNATURE-----

--oLBj+sq0vYjzfsbl--
 
Z

Zachary P. Landau

--ALfTUftag+2gvp1h
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
Hi,
=20
Since you are using Gtk, maybe the Gdk::Input.add method
could help you. You can invoke it like this:
=20
Gdk::Input.add(my_io.to_i, Gdk::Input::Condition::READ) do
#block to execute when data is ready in the io
end
=20
This is the version for gtk2, the gtk (1.2) version is a
little different.
You must have a Gtk.main loop for this to work.
I hope this is helpful.

Well, unfortunately I had the same problem. But thanks for telling me
about Gdk::Input, once I get this working I'll move to that method. It
seems to be a little cleaner than what I was doing.

--
Zachary P. Landau <[email protected]>
GPG: gpg --recv-key 0x24E5AD99 | http://kapheine.hypa.net/kapheine.asc

--ALfTUftag+2gvp1h
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBMoDhCwWyMCTlrZkRAkmhAJ9lwylhYHWgY0esCVVGbjPWvYTefwCeI44x
DbrcHjIzpX93oGNx5G6q57w=
=eNat
-----END PGP SIGNATURE-----

--ALfTUftag+2gvp1h--
 
N

nobu.nokada

Hi,

At Sun, 29 Aug 2004 07:28:59 +0900,
Zachary P. Landau wrote in [ruby-talk:110845]:
The mailing list has some posts about blocking problems, but they are
related to sockets and pipes. As I mentioned earlier, the above code
works when CUECAT_DEV is a pipe.

It sounds like as the issue mention at [ruby-talk:109668].
What's the version of the kernel do you use? Apparently, some
linux device drivers feel not to work fine with select(2).
 
Z

Zachary P. Landau

--/unnNtmY43mpUSKx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,
=20
At Sun, 29 Aug 2004 07:28:59 +0900,
Zachary P. Landau wrote in [ruby-talk:110845]:
The mailing list has some posts about blocking problems, but they are
related to sockets and pipes. As I mentioned earlier, the above code
works when CUECAT_DEV is a pipe.
=20
It sounds like as the issue mention at [ruby-talk:109668].
What's the version of the kernel do you use? Apparently, some
linux device drivers feel not to work fine with select(2).

Yeah, it does sound like the same problem. I'm using 2.4.26 patched
with the cuecat driver from [1].

[1] http://webperso.easyconnect.fr/om.the/web/cuecat/

--
Zachary P. Landau <[email protected]>
GPG: gpg --recv-key 0x24E5AD99 | http://kapheine.hypa.net/kapheine.asc

--/unnNtmY43mpUSKx
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBMpSjCwWyMCTlrZkRAsLVAJwNpGcYdib0jTz5gFSd7Glv/AvfOACfZER5
NuBSZs8USSyevSYNWYyNqTU=
=Cjor
-----END PGP SIGNATURE-----

--/unnNtmY43mpUSKx--
 
Z

Zachary P. Landau

--OZkY3AIuv2LYvjdk
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi,
=20
At Mon, 30 Aug 2004 11:45:01 +0900,
Zachary P. Landau wrote in [ruby-talk:110919]:
Yeah, it does sound like the same problem. I'm using 2.4.26 patched
with the cuecat driver from [1].
=20
[1] http://webperso.easyconnect.fr/om.the/web/cuecat/
=20
It doesn't implement `poll' function.

Ahh okay, so the driver is at fault. Thanks a lot for your help.

--
Zachary P. Landau <[email protected]>
GPG: gpg --recv-key 0x24E5AD99 | http://kapheine.hypa.net/kapheine.asc

--OZkY3AIuv2LYvjdk
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.5 (GNU/Linux)

iD8DBQFBMy2kCwWyMCTlrZkRAoyZAJ9IWu9jFEE6qQtpTuO2rKEVeVeo+ACfV+0Y
AfNXITNgQ0e/hdyfK7MPom8=
=sLKd
-----END PGP SIGNATURE-----

--OZkY3AIuv2LYvjdk--
 
P

Paul Brannan

The problem is, I can't avoid blocking. There is a GTK application, and
then a separate thread that tries to read barcodes and whenever it finds
one, it tells the GTK app.

So my code looks like this:

Thread.new do
File.open(CUECAT_DEV, File::RDONLY | File::NONBLOCK) do |cuecat|
loop do
id, barcode_type, barcode = cuecat.gets.split(/,/)
# do stuff with the barcode
end
end
end

Some notes:

1. IIRC, #gets always has the potential to block, even if you are in
non-blocking mode (as for why it doesn't relinquish control back to
the GUI thread, I don't know; that's a totally different question)
2. Gtk has a method for dealing with long-running IO operations;
essentially what you want to do is register it with Gtk using
Gtk.input_add(io, Gdk::INPUT_READ) { ... } (I'm still using Gtk 1.2;
this may be a little different in 2.x?)
3. This will give you a callback whenever data are available, but this
doesn't mean an entire line is available or that multiple lines are
not available. So for that I use:
data = io.sysread(512)
@data << data
while line = @data.slice!(/.*\n/) do
line.strip!
handle_line(line)
end

To put it together, instead of starting a new thread, you can instead
use:

cuecat = File.open(CUECAT_DEV, File::RDONLY)
Gtk.input_add(io, Gdk::INPUT_READ) do
data = io.sysread(512)
@data << data
while line = @data.slice!(/.*\n/) do
id, barcode_type, barcode = cuecat.gets.split(/,/)
# do stuff with the barcode
end
end

I think this will make your life much simpler (especially since you
don't have all those thread-safety issues to worry about).

Paul
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top