Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Tk : non blocking Tk.mainloop

Reply
Thread Tools

Tk : non blocking Tk.mainloop

 
 
Juju SL
Guest
Posts: n/a
 
      04-13-2011
Hi all,

I'm new in this forum (but I have been following it for months)

I did some canvas tests on my Debian Squeeze with Ruby 1.8 + Tk, and
everything was OK.

Then I chose to move to Ruby 1.9 ; so I cleaned my old Ruby packages and
installed "ruby1.9.1-full package", which comes with Tk8.4

My problem is I can't get Ruby TK programs run properly, because the
Tk.mainloop is non blocking ; my program exists immediately, I only see
the Tk canvas appear and disappear.

This occurs even on the simpliest program, like :
require 'tk'
rr=TkRoot.new
cc=TkCanvas.new(rr)
cc.pack
Tk.mainloop

Running it under IRB, the window appears correctly.

Any clue about this behaviour and how to make Tk.mainloop work as
expected ? Thanks

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
botp
Guest
Posts: n/a
 
      04-13-2011
On Thu, Apr 14, 2011 at 1:20 AM, Juju SL <(E-Mail Removed)> wrote:
> Tk.mainloop is non blocking ; my program exists immediately, I only see
> the Tk canvas appear and disappear.


fwiw, it should not exit, mine does not. i think nahi good help you further.
best regards -botp

 
Reply With Quote
 
 
 
 
Hidetoshi NAGAI
Guest
Posts: n/a
 
      04-24-2011
Hi,

I'm very sorry for my late response.

From: Juju SL <(E-Mail Removed)>
Subject: Tk : non blocking Tk.mainloop
Date: Thu, 14 Apr 2011 02:20:37 +0900
Message-ID: <(E-Mail Removed)>
> I did some canvas tests on my Debian Squeeze with Ruby 1.8 + Tk, and
> everything was OK.
>
> Then I chose to move to Ruby 1.9 ; so I cleaned my old Ruby packages and
> installed "ruby1.9.1-full package", which comes with Tk8.4
>
> My problem is I can't get Ruby TK programs run properly, because the
> Tk.mainloop is non blocking ; my program exists immediately, I only see
> the Tk canvas appear and disappear.


I don't use Debian. I couldn't re-generate your trouble on my environment.
It may depend on race condition of native threads.

Could you try the followings and report the results?

(1) If you call Tk.mainloop on the main thread only,
please call the follwing line berore "require 'tk'".
----------------------------------------------------------------------
module TkCore; RUN_EVENTLOOP_ON_MAIN_THREAD = true; end
----------------------------------------------------------------------

(2) Please run your simple script, which occurs your trouble, with -d option.
e.g.
----------------------------------------------------------------------
ruby -d your_script.rb > exec.log 2>&1
----------------------------------------------------------------------
If it has same trouble, please send me the log file.

(3) Please apply the following patch.
If it has same trouble, please send the log when running with -d option.
================================================== =
--- tk.rb-orig 2011-04-25 06:37:19.000000000 +0900
+++ tk.rb 2011-04-25 06:54:13.000000000 +0900
@@ -1271,6 +1271,7 @@
}
set __initial_state_of_rubytk__ 1
trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__
+update
EOS

begin
@@ -1301,7 +1302,8 @@
}

until INTERP_THREAD[:interp]
- Thread.pass
+ #Thread.pass
+ INTERP_THREAD.run
end
# INTERP_THREAD.run
raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception
================================================== =
--
Hidetoshi NAGAI ((E-Mail Removed))
Department of Artificial Intelligence, Kyushu Institute of Technology

 
Reply With Quote
 
Juju SL
Guest
Posts: n/a
 
      04-28-2011
Hi,

Thank you for this answer Hidetoshi.

So, as I had gone back to Ruby 1.8, I desinstalled its packages and
reinstalled the 1.9 ones.

I tried your first suggestion with my simple script and the script ran
OK.

Then I tried another more complicated script, which did not work last
time ; it now runs OK too with your first hack.

I haven't tried your third suggestion, as I prefer to keep my packages
clean ; I keep it in mind in case the first hack does not solve my
problems.

Thanks a lot for your help ; I will keep you aware if my problem occurs
again.

Best regards

JujuSL

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Hidetoshi NAGAI
Guest
Posts: n/a
 
      04-29-2011
From: Juju SL <(E-Mail Removed)>
Subject: Re: Tk : non blocking Tk.mainloop
Date: Fri, 29 Apr 2011 06:03:21 +0900
Message-ID: <(E-Mail Removed)>
> I tried your first suggestion with my simple script and the script ran
> OK.
>
> Then I tried another more complicated script, which did not work last
> time ; it now runs OK too with your first hack.


First of all, it's a good news that your script worked properly.

However, the first counterplan is not a good one.
Because, when you use it, you cannot call Tk.mainloop in a sub-thread
(e.g. "Thread.new{Tk.mainloop}" doesn't work).

> I haven't tried your third suggestion, as I prefer to keep my packages
> clean ; I keep it in mind in case the first hack does not solve my
> problems.


I can understand your care. So, I can't force you to try the third
counterplan. But I need your help to fix the problem, because I can't
generate the problem.
If you try the third one temporally and it is effective, I can commit
the patch for the next release of Ruby.
Again, I never force you. But your trial report has very high value.
--
Hidetoshi NAGAI ((E-Mail Removed))
Department of Artificial Intelligence, Kyushu Institute of Technology

 
Reply With Quote
 
Juju SL
Guest
Posts: n/a
 
      04-29-2011
Hi Hidetoshi,

I understand your need and as I asked for help, I have to help you back


So I applied the patch to tk.rb :
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
...
set __initial_state_of_rubytk__ 1
trace add variable __initial_state_of_rubytk__ unset
__startup_rbtk_mainloop__
update
EOS

begin
begin
#TclTkLib.mainloop_abort_on_exception =3D false
...
and
...
}

until INTERP_THREAD[:interp]
#Thread.pass
INTERP_THREAD.run
end
# INTERP_THREAD.run
raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of?
Exception
...
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D

Running the small script gives the same problem ; here is the end of the
debug output showing an exception :
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D
tcltklib: destroy root widget
tcltklib: check `finalize-hook-proc'
tcltklib: check `foreach' & `after'
tcltklib: cancel after callbacks
tcltklib: finish ip_finalize
Exception `TypeError' at /usr/lib/ruby/1.9.1/tk.rb:1283 - exception
class/object expected
tcltklib: eventloop_ensure: current-thread : 8802278
tcltklib: eventloop_ensure: eventloop-thread : 8802278
tcltklib: eventloop-ensure: new eventloop-thread -> 4
tcltklib: finish current eventloop 8802278
tcltklib: ip is deleted
tcltklib: ip is deleted
tcltklib: ip is deleted
tcltklib: delete deleted IP
tcltklib: free Tcl Interp 881a678
tcltklib: complete freeing Tcl Interp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D

But the weird thing is that sometimes it runs OK ! (once every 6 ou 7
times) ; I just run the same command again and again...

Hope this will help !

Best regards
St=C3=A9phane

-- =

Posted via http://www.ruby-forum.com/.=

 
Reply With Quote
 
Hidetoshi NAGAI
Guest
Posts: n/a
 
      04-29-2011
From: Juju SL <(E-Mail Removed)>
Subject: Re: Tk : non blocking Tk.mainloop
Date: Sat, 30 Apr 2011 04:37:52 +0900
Message-ID: <(E-Mail Removed)>
> I understand your need and as I asked for help, I have to help you back
>


I'm sorry that I bothered you about it, and thank you for your help.

> Running the small script gives the same problem ; here is the end of the

(snip)
> But the weird thing is that sometimes it runs OK ! (once every 6 ou 7
> times) ; I just run the same command again and again...


Well, there is no wrong code about compatibility with your Tcl/Tk and
other libraries. And probably, it means that the trouble depends on
the race condition between a main thread and a background eventloop
(with initializing Tcl/Tk interpreter) thread.
I can focus to check when such race condition occurs.
Thank you for your report.
--
Hidetoshi NAGAI ((E-Mail Removed))
Department of Artificial Intelligence, Kyushu Institute of Technology

 
Reply With Quote
 
Hidetoshi NAGAI
Guest
Posts: n/a
 
      05-02-2011
From: Hidetoshi NAGAI <(E-Mail Removed)>
Subject: Re: Tk : non blocking Tk.mainloop
Date: Sat, 30 Apr 2011 07:27:07 +0900
Message-ID: <(E-Mail Removed) >
> I can focus to check when such race condition occurs.


Could you try the followiing patch?

--- ../ruby-1.9.2-p0.orig/ext/tk/lib/tk.rb 2010-06-29 06:44:06.000000000 +0900
+++ ext/tk/lib/tk.rb 2011-05-02 18:16:29.000000000 +0900
@@ -1236,6 +1236,9 @@
raise e
end

+ interp.mainloop_abort_on_exception = true
+ Thread.current.instance_variable_set("@interp", interp)
+
status = [nil]
def status.value
self[0]
@@ -1271,19 +1274,23 @@
}
set __initial_state_of_rubytk__ 1
trace add variable __initial_state_of_rubytk__ unset __startup_rbtk_mainloop__
+
+# complete initializing
+ruby {TkCore::INTERP_THREAD[:interp] = TkCore::INTERP_THREAD.instance_variable_get('@inte rp')}
EOS

begin
begin
#TclTkLib.mainloop_abort_on_exception = false
#Thread.current[:status].value = TclTkLib.mainloop(true)
- interp.mainloop_abort_on_exception = true
- Thread.current[:interp] = interp
+ #interp.mainloop_abort_on_exception = true
+ #Thread.current[:interp] = interp
Thread.current[:status].value = interp.mainloop(true)
rescue SystemExit=>e
Thread.current[:status].value = e
rescue Exception=>e
Thread.current[:status].value = e
+ p e if $DEBUG
retry if interp.has_mainwindow?
ensure
INTERP_MUTEX.synchronize{ INTERP_ROOT_CHECK.broadcast }
@@ -1300,12 +1307,20 @@
end
}

+ # check a Tcl/Tk interpreter is initialized
until INTERP_THREAD[:interp]
- Thread.pass
+ # Thread.pass
+ INTERP_THREAD.run
end
+
# INTERP_THREAD.run
raise INTERP_THREAD[:interp] if INTERP_THREAD[:interp].kind_of? Exception

+ # check an eventloop is running
+ while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil?
+ INTERP_THREAD.run
+ end
+
INTERP = INTERP_THREAD[:interp]
INTERP_THREAD_STATUS = INTERP_THREAD[:status]

@@ -1316,6 +1331,9 @@
INTERP_THREAD.kill
end
}
+
+ # (for safety's sake) force the eventloop to run
+ INTERP_THREAD.run
end

def INTERP.__getip

--
Hidetoshi NAGAI ((E-Mail Removed))
Department of Artificial Intelligence, Kyushu Institute of Technology

 
Reply With Quote
 
Juju SL
Guest
Posts: n/a
 
      05-02-2011
So, I patched manually the tk.rb file :
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
# diff tk.rb.ORIG tk.rb

1238a1239,1241
> interp.mainloop_abort_on_exception =3D true
> Thread.current.instance_variable_set("@interp", interp)
>

1273a1277,1279
> # complete initializing
> ruby {TkCore::INTERP_THREAD[:interp] =3D

TkCore::INTERP_THREAD.instance_variable_get('@inte rp')}
>

1280,1281c1286,1287
< interp.mainloop_abort_on_exception =3D true
< Thread.current[:interp] =3D interp
---
> # interp.mainloop_abort_on_exception =3D true
> # Thread.current[:interp] =3D interp

1286a1293
> p e if $DEBUG

1302a1310
> # check a Tcl/Tk interpreter is initialized

1304c1312,1313
< Thread.pass
---
> # Thread.pass
> INTERP_THREAD.run

1308a1318,1322
> # check an eventloop is running
> while INTERP_THREAD.alive? && TclTkLib.mainloop_thread?.nil?
> INTERP_THREAD.run
> end
>

1318a1333,1336
>
> # (for safety's sake) force the eventloop to run
> INTERP_THREAD.run
>

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Unfortunately, my small scripts ends with an exception :
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
tcltklib: delete slaves
tcltklib: destroy root widget
tcltklib: check `finalize-hook-proc'
tcltklib: check `foreach' & `after'
tcltklib: cancel after callbacks
tcltklib: finish ip_finalize
Exception `TypeError' at /usr/lib/ruby/1.9.1/tk.rb:1288 - exception
class/object expected
tcltklib: eventloop_ensure: current-thread : 9e62658
tcltklib: eventloop_ensure: eventloop-thread : 9e62658
tcltklib: eventloop-ensure: new eventloop-thread -> 4
tcltklib: finish current eventloop 9e62658
tcltklib: ip is deleted
tcltklib: ip is deleted
tcltklib: ip is deleted
tcltklib: delete deleted IP
tcltklib: free Tcl Interp 9e7ae68
tcltklib: complete freeing Tcl Interp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3 D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Line 1288 is : Thread.current[:status].value =3D interp.mainloop(true)

Best regards
St=C3=A9phane

-- =

Posted via http://www.ruby-forum.com/.=

 
Reply With Quote
 
Hidetoshi NAGAI
Guest
Posts: n/a
 
      05-03-2011
Thank you for your reply.

From: Juju SL <(E-Mail Removed)>
Subject: Re: Tk : non blocking Tk.mainloop
Date: Tue, 3 May 2011 05:46:55 +0900
Message-ID: <(E-Mail Removed)>
> So, I patched manually the tk.rb file :


You don't need manual patch. Please use "patch" command.

# Or, packaged version of tk.rb is not a normal one of ruby192p0?
# If so, please tell me the version of your package.

> Unfortunately, my small scripts ends with an exception :


Hmmm... Maybe, I misunderstood the reason of the trouble.
The exception is not important.
It is a normal situation when a Tcl/Tk interpreter is deleted at exit.

I want to know when and how Tk.mainloop exits.
Could you send me a *FULL* debug log with tk.rb (patched by previous
(ruby-talk:382536) patch) patched by the following?

--- tk.rb~ 2011-05-02 18:16:29.000000000 +0900
+++ tk.rb 2011-05-03 11:18:17.000000000 +0900
@@ -1852,32 +1852,56 @@
TclTkLib.mainloop(check_root)

else ### Ruby 1.9 !!!!!
+p :log001
unless TkCore::INTERP.default_master?
+p :log002
# [MultiTkIp] slave interp ?
return TkCore::INTERP._thread_tkwait('window', '.') if check_root
end
+p :log003

# like as 1.8, withdraw a root widget before calling Tk.mainloop
TkCore::INTERP._eval_without_enc('catch {unset __initial_state_of_rubytk__}')
+p :log004
INTERP_THREAD.run
+p :log005

begin
TclTkLib.set_eventloop_window_mode(true)
+p :log006
if check_root
+p :log007
INTERP_MUTEX.synchronize{
+p :log008
INTERP_ROOT_CHECK.wait(INTERP_MUTEX)
+p :log009
status = INTERP_THREAD_STATUS.value
+p [:log010, status]
if status && TkCore::INTERP.default_master?
INTERP_THREAD_STATUS.value = nil if $SAFE < 4
+p :log011
raise status if status.kind_of?(Exception)
end
+p :log012
}
else
- INTERP_THREAD.value
+p :log013
+ # INTERP_THREAD.value
+ begin
+ INTERP_THREAD.value
+ rescue Exception => e
+p [:log014, e]
+ raise e
+ end
end
+ rescue Exception => e
+p [:log015, e]
+ raise e
ensure
+p :log016
TclTkLib.set_eventloop_window_mode(false)
end
+p :log017
end
end



--
Hidetoshi NAGAI ((E-Mail Removed))
Department of Artificial Intelligence, Kyushu Institute of Technology

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Non blocking socket keep blocking on read ? Serge Savoie Ruby 4 10-01-2008 03:16 PM
Switching from Non-Blocking to Blocking IO Christian Java 5 12-02-2007 11:24 PM
Non-blocking and semi-blocking Sockets class. nukleus Java 14 01-22-2007 08:22 PM
Blocking and non blocking assignment in VHDL Hendra Gunawan VHDL 1 04-08-2004 06:03 AM
blocking i/o vs. non blocking i/o (performance) Andre Kelmanson C Programming 3 10-12-2003 02:09 PM



Advertisments