Hi Guys, i create a process in a child-windows with io.popen. If users closes this window, for example via click on "X" i need to react in the parent window. How can i catch the evt_close of this child-process? -- Posted via http://www.ruby-forum.com/.
Quintus
2012-Sep-13 11:25 UTC
[wxruby-users] Catch Close-Event from child-window created with io.popen
Am Thu, 13 Sep 2012 08:59:47 +0200 schrieb "Daniel S." <lists at ruby-forum.com>:> Hi Guys, > > i create a process in a child-windows with io.popen. > > If users closes this window, for example via click on "X" i need to > react in the parent window. > > How can i catch the evt_close of this child-process?If I get you right, you run a Ruby application via IO.popen and want your parent process to do something? Something like this: ================================IO.popen("ruby myapp.rb"){...stuff...} ================================ ? So you have three possibilities now: 1. EVT_CLOSE usually means your child application is going to exit. So just use IO.popen with the block form, which will wait until your child process has finished. 2. If you can?t use the block form for some reason, use Process.wait which will wait for all child processes to exit. 3. Assuming you #veto the close event, but want your parent process to take action nevertheless, you can use process signals to achieve what you want. In the parent process, register a signal handler for your "reaction": ================================Signal.trap("SIGUSR1") do puts "Hi, I''ve been notified!" # or do whatever you want end ================================ In the child process, register an event handler for the EVT_CLOSE event that notifies your parent process (Process.ppid returns the PID of your process? parent process): ================================evt_close do |event| Process.kill("SIGUSR1", Process.ppid) event.veto # Do not close the window end ================================ Or if you meant it the other way round, having your child process to react when the parent process gets EVT_CLOSE, you could catch the EVT_CLOSE in the parent process and send a signal to the child process. Example (using the open4 gem): ================================require "open4" require "wx" class MainFrame < Wx::Frame include Wx def initialize(parent = nil) super(parent, title: "Test", size: [400, 400]) StaticText.new(self, label: "Test app", pos: [20, 20]) @button = Button.new(self, label: "Click me", pos: [20, 50]) evt_button(@button, :on_button_click) evt_close(:on_close) end private def on_button_click(event) # Note you cannot use the block form @childpid, @childstdin, @childstdout, @childstderr = \ Open4.popen4("sleep") end def on_close(event) Process.kill("SIGTERM", @childpid) event.skip # Otherwise closing is prohibited end end class MyApp < Wx::App def on_init @mainwindow = MainFrame.new @mainwindow.show end end ================================ This application will send SIGTERM to the "sleep" child process when EVT_CLOSE is received. Vale, Marvin -- Blog: http://pegasus-alpha.eu/blog ASCII-Ribbon-Kampagne () | ASCII Ribbon Campaign () - Stoppt HTML-E-Mail /\ | - Against HTML E-Mail /\ - Stoppt propriet?re Anh?nge | - Against proprietary attachments www.asciiribbon.org/index-de.html | www.asciiribbon.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: not available URL: <http://rubyforge.org/pipermail/wxruby-users/attachments/20120913/53e78744/attachment.bin>
Daniel S.
2012-Sep-13 14:46 UTC
[wxruby-users] Catch Close-Event from child-window created with io.popen
Hi Marvin, thx for ur long answer, but this is not exactly what i wanted, because my childprocess is not really a second ruby process. In my case i am using Gnuplot in the childwindow and coontrol it via buttons in the parent window. So here is my example: At first i create my parent window with some buttons and the following code to invoke the child process: ... def on_buttonclick @gnuplot = Plot.new(filelist) end def on_anotherbuttonclick @gnuplot.do_something end ... Here is what my Plot-Class does: class Plot def initialize(filelist) @gp=IO.popen("gnuplot","w+") @gp.puts("plot #{filelist}") end def do_something @gp.puts("do something") end ... end Situation after Click on first button: - Parent window is open with two button - Gnuplot-Window has been openend as a child of parentwindow with some plot - both are idle - After Click on second button the childprocess is forced to do something, this is what the parent process should do. Now my problem: If the user closes the Childwindow (For example Alt-F4, or click on "X" the Window closes, but the object @gnuplot still exists in memory. If this happens i want to react in ParentProcess for example with @gnuplot.close or disable some buttons which have no function any longer when Childwindows doesnt exist anymore. evt_close in my Plot-Class does not seem to work, because this event is not thrown in case of clicking on "X" or Alr-F4. So the question is: How to catch those (User-)Events? If i could catch these events i could use your solution with SIGTERM -- Posted via http://www.ruby-forum.com/.
Quintus
2012-Sep-13 20:57 UTC
[wxruby-users] Catch Close-Event from child-window created with io.popen
Am Thu, 13 Sep 2012 16:46:35 +0200 schrieb "Daniel S." <lists at ruby-forum.com>:> Hi Marvin, > thx for ur long answer, but this is not exactly what i wanted, > because my childprocess is not really a second ruby process. In my > case i am using Gnuplot in the childwindow and coontrol it via > buttons in the parent window.You cannot listen to events to other processes. So if GnuPlot doesn?t have a possibility to tell you when its main window is closed, you can?t check this without relying on dirty hacks such as making xdotool check the visibility of the window regularily by means of a Wx::Timer.> Situation after Click on first button: > - Parent window is open with two button > - Gnuplot-Window has been openend as a child of parentwindow with > some plot > - both are idle > - After Click on second button the childprocess is forced to do > something, this is what the parent process should do.First for clarity: This way the GnuPlot window is *not* a child window of your application. It?s the main window of a completely autonome and separate process. The GnuPlot *process* is a child process of your Ruby process, but the window belongs to the child process, not to your process. I don?t know GnuPlot, but when its main window exits (as a result to [Alt]+[F4] or clicking on the close button) I suspect the process running the window dies, doesn?t it? If you?re developing for a *nix platform there?s a special process signal, SIGCHLD, which is fired on your process when a child process dies. Any *nix application (including Ruby applications) can register a handler for this signal, so you can for example do (IO.popen creates child processes, and #spawn does so as well): ====================================spawn("sleep 5") Signal.trap("SIGCHLD") do puts "This was it." puts "But for $500.000 I will send you the body." exit end puts "If you don''t pay $1.000.000 I will kill this child." loop do puts "I''m waiting..." sleep 0.5 end ==================================== You should be able to combine this with your usecase[1]. I however am not sure how wxRuby reacts if you try to modify wx stuff from this asynchronously run code; I often saw segfaults or arcane error messages when I even tried this with threads, so I cannot predict what happens from within signal handlers. What you probably can do safely is registering a callback to run as soon as possible (probably utilising Timer.after with a very short time interval) which will then be run from within the wx eventloop and therefore be safe.> So the question is: How to catch those (User-)Events?As said: There?s no way to listen to events for another process (apart from using GDB, I suppose).> If i could catch these events i could use your solution with SIGTERMVale, Marvin [1] I mean the concept employed by the code, not the way this hypothetic kidnapper acts, of course. Btw. from the code you can see he never had the intention to leave the child alive after receiving the money. -- Blog: http://pegasus-alpha.eu/blog ASCII-Ribbon-Kampagne () | ASCII Ribbon Campaign () - Stoppt HTML-E-Mail /\ | - Against HTML E-Mail /\ - Stoppt propriet?re Anh?nge | - Against proprietary attachments www.asciiribbon.org/index-de.html | www.asciiribbon.org -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 490 bytes Desc: not available URL: <http://rubyforge.org/pipermail/wxruby-users/attachments/20120913/a4817015/attachment.bin>
Daniel S.
2012-Sep-13 21:31 UTC
[wxruby-users] Catch Close-Event from child-window created with io.popen
I think my problem is, that the plotwindow is NOT a childwindow of my parent, but a childwindow of the gnuplot-process, which runs in background even if the plotwindow is closed by user. So i need to close the gnuplot-process if user closes the plotwindow, which has nothing to do with wxruby. I''ll try a gnuplot-forum for this. Thx for your help! -- Posted via http://www.ruby-forum.com/.
Daniel S.
2012-Sep-13 21:38 UTC
[wxruby-users] Catch Close-Event from child-window created with io.popen
> First for clarity: This way the GnuPlot window is *not* a child window > of your application. It?s the main window of a completely autonome and > separate process. The GnuPlot *process* is a child process of your Ruby > process, but the window belongs to the child process, not to your > process.okay, this was my problem...> > I don?t know GnuPlot, but when its main window exits (as a result to > [Alt]+[F4] or clicking on the close button) I suspect the process > running the window dies, doesn?t it?No, it does''nt. I''ll check some gnuplot forums to realize this behavior. After this is can use SIGCHLD, i think As an alternative i''ll prevent the gnuplot window to be closed by user (don''t know yet how to do so) and implement a "close window"-button in my parent which kills the whole gnuplot-process... Thx for your help! -- Posted via http://www.ruby-forum.com/.