gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r12067: Stop relying on signals to k


From: Bastiaan Jacques
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12067: Stop relying on signals to kill gnash when launched from the plugin.
Date: Tue, 16 Mar 2010 19:04:59 +0100
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12067
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Tue 2010-03-16 19:04:59 +0100
message:
  Stop relying on signals to kill gnash when launched from the plugin. 
  Instead, add another file descriptor (pipe) argument to gnash, which the 
  (plugin-compatible) GUI monitors for SIGHUP. Additionally:
  
  plugin/plugin.cpp: Don't leak the GIOChannel.
  gui/gtk.cpp: Remove LIRC callback that does nothing.
modified:
  gui/Player.cpp
  gui/Player.h
  gui/gnash.cpp
  gui/gtk.cpp
  gui/gtksup.h
  gui/gui.cpp
  gui/gui.h
  plugin/plugin.cpp
  plugin/plugin.h
=== modified file 'gui/Player.cpp'
--- a/gui/Player.cpp    2010-03-14 02:26:46 +0000
+++ b/gui/Player.cpp    2010-03-16 18:04:59 +0000
@@ -104,6 +104,7 @@
     _fpsDebugTime(0.0),
 #endif
     _hostfd(-1),
+    _controlfd(-1),
     _startFullscreen(false),
     _hideMenu(false)
 {
@@ -418,6 +419,10 @@
     // Set host requests fd (if any)
     if ( _hostfd != -1 ) root.setHostFD(_hostfd);
 
+    if (_controlfd != -1) {
+        _gui->setFDCallback(_controlfd, boost::bind(&Gui::quit, 
boost::ref(_gui)));
+    }
+
     _gui->setStage(&root);
     
     // When startStopped is true, stop here after the stage has been 

=== modified file 'gui/Player.h'
--- a/gui/Player.h      2010-03-14 02:26:46 +0000
+++ b/gui/Player.h      2010-03-16 18:04:59 +0000
@@ -148,6 +148,10 @@
     int getHostFD() const {
         return _hostfd;
     }
+
+    void setControlFD(int fd) {
+        _controlfd = fd;
+    }
     
     void setStartFullscreen(bool x) {
         _startFullscreen = x;
@@ -354,6 +358,8 @@
     // Filedescriptor to use for host application requests, -1 if none
     int _hostfd;
     
+    int _controlfd;
+
     // Whether to start Gnash in fullscreen mode.
     // (Or what did you think it meant?)
     bool _startFullscreen;

=== modified file 'gui/gnash.cpp'
--- a/gui/gnash.cpp     2010-03-14 02:26:46 +0000
+++ b/gui/gnash.cpp     2010-03-16 18:04:59 +0000
@@ -141,6 +141,8 @@
             "\"FlashVars=A=1&b=2\")\n") 
     << _("  -F,  --fd <fd>           Filedescriptor to use for external "
             "communications\n") 
+    << _("  -G,  --controlfd <fd>    File descriptor for external application"
+            " control\n")
 #ifdef GNASH_FPS_DEBUG
     << _("  -f,  --debug-fps num     Print FPS every num seconds (float)\n") 
 #endif // def GNASH_FPS_DEBUG
@@ -236,6 +238,7 @@
         { 'V', "version",           Arg_parser::no  },        
         { 'f', "debug-fps",         Arg_parser::yes },        
         { 'F', "fd",                Arg_parser::yes },
+        { 'G', "controlfd",         Arg_parser::yes },
         { 'A', "dump",              Arg_parser::yes },
         { 259, "screenshot",        Arg_parser::yes },
         { 260, "screenshot-file",   Arg_parser::yes },
@@ -329,6 +332,17 @@
                     player.setHostFD ( fd );
                     break;
                 }
+                case 'G':
+                {
+                    const int fd = parser.argument<long>(i);
+                    if (fd < 1) {
+                        cerr << boost::format(_("Invalid host communication "
+                                    "filedescriptor %d\n")) % fd << endl;
+                        exit(EXIT_FAILURE);
+                    }
+                    player.setControlFD ( fd );
+                    break;
+                }
                 case 'j':
                     widthGiven = true;
                     player.setWidth(parser.argument<long>(i));

=== modified file 'gui/gtk.cpp'
--- a/gui/gtk.cpp       2010-03-14 02:26:46 +0000
+++ b/gui/gtk.cpp       2010-03-16 18:04:59 +0000
@@ -109,7 +109,10 @@
     void menuQualityLow(GtkMenuItem *menuitem, gpointer instance); 
     void menuQualityMedium(GtkMenuItem *menuitem, gpointer instance); 
     void menuQualityHigh(GtkMenuItem *menuitem, gpointer instance); 
-    void menuQualityBest(GtkMenuItem *menuitem, gpointer instance); 
+    void menuQualityBest(GtkMenuItem *menuitem, gpointer instance);
+
+    gboolean fd_callback_handler(GIOChannel *source, GIOCondition condition,
+                                 gpointer data);
 
     void timeoutQuit(gpointer data);
 
@@ -151,13 +154,6 @@
 
 }
 
-#ifdef USE_LIRC
-// This is global so it can be accessed by the event handler, which
-// isn't part of this class. 
-Lirc *lirc;
-bool lirc_handler(void*, int, void* data);
-#endif
-
 GtkGui::~GtkGui()
 {
 }
@@ -326,10 +322,7 @@
     
 #ifdef USE_LIRC
     lirc = new Lirc();
-    if (lirc->init("/dev/lircd")) {
-        int fd = lirc->getFileFd();
-        addFDListener(fd, lirc_handler, &fd);
-    } else {
+    if (!lirc->init("/dev/lircd")) {
         log_debug(_("LIRC daemon not running"));
     }
 #endif
@@ -367,8 +360,9 @@
     g_timeout_add(timeout, (GSourceFunc)timeoutQuit, this);
 }
 
+
 bool
-GtkGui::addFDListener(int fd, callback_t callback, void* data)
+GtkGui::watchFD(int fd)
 {
     // NOTE: "The default encoding for GIOChannel is UTF-8. If your application
     // is reading output from a command using via pipe, you may need to set the
@@ -381,13 +375,13 @@
         return false;
     }
     
-    if (!g_io_add_watch (gio_read, GIOCondition(G_IO_IN | G_IO_HUP),
-                         GIOFunc (callback), data)) {
+    if (!g_io_add_watch (gio_read, GIOCondition(G_IO_HUP),
+                         GIOFunc (fd_callback_handler), this)) {
         g_io_channel_unref(gio_read);
-        return false;    
+        return false;
     }
     
-    return true;    
+    return true;
 }
 
 void
@@ -2244,19 +2238,6 @@
 
 }
 
-#ifdef USE_LIRC
-bool
-lirc_handler(void*, int, void* /*data*/)
-{ 
-    
-    // want to remove this handler. You may want to close fd.
-    log_debug("%s\n", lirc->getButton());
-  
-    // Want to keep this handler
-    return true;
-}
-#endif
-
 // This assumes that the parent of _drawingArea is _window, which
 // isn't the case in the plugin fullscreen (it's _overlay). Currently
 // we return from fullscreen when Gui::stop() is called, which
@@ -2843,6 +2824,18 @@
     gui->setQuality(QUALITY_BEST);
 }
 
+gboolean
+fd_callback_handler(GIOChannel *source, GIOCondition condition,
+                    gpointer data)
+{
+    Gui* gui = static_cast<Gui*>(data);
+
+    gui->callCallback(g_io_channel_unix_get_fd (source));
+
+    return true;
+}
+
+
 } // anonymous namespace
 
 } // end of namespace gnash

=== modified file 'gui/gtksup.h'
--- a/gui/gtksup.h      2010-03-14 02:26:46 +0000
+++ b/gui/gtksup.h      2010-03-16 18:04:59 +0000
@@ -52,9 +52,6 @@
 {
 public:
 
-    /// For the Gtk GUI FD listener, whatever that might be for.
-    typedef bool (*callback_t)(void*, int, void *data);
-
     GtkGui(unsigned long xid, float scale, bool loop, RunResources& r);
     
     virtual ~GtkGui();
@@ -109,7 +106,7 @@
     ///        callback should return false if the listener is to be removed.
     /// @param data A pointer to a user-defined data structure.
     /// @return true on success, false on failure.
-    bool addFDListener(int fd, callback_t callback, void* data);
+    bool watchFD(int fd);
 
     /// Grab focus so to receive all key events
     //

=== modified file 'gui/gui.cpp'
--- a/gui/gui.cpp       2010-03-14 02:26:46 +0000
+++ b/gui/gui.cpp       2010-03-16 18:04:59 +0000
@@ -1324,6 +1324,30 @@
 }
 
 void
+Gui::setFDCallback(int fd, boost::function<void ()> callback)
+{
+    _fd_callbacks[fd] = callback;
+
+    watchFD(fd);
+}
+
+
+void
+Gui::callCallback(int fd)
+{
+    std::map<int, boost::function<void ()> >::iterator it = 
_fd_callbacks.find(fd);
+
+    if (it == _fd_callbacks.end()) {
+        log_error("Attempted to call a callback for an unregistered fd.");
+        return;
+    }
+
+    boost::function<void()>& f = it->second;
+
+    f();
+}
+
+void
 ScreenShotter::saveImage(const std::string& id) const
 {
     // Replace all "%f" in the filename with the frameAdvance.

=== modified file 'gui/gui.h'
--- a/gui/gui.h 2010-03-14 06:02:38 +0000
+++ b/gui/gui.h 2010-03-16 18:04:59 +0000
@@ -37,6 +37,7 @@
 
 #include <boost/intrusive_ptr.hpp>
 #include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
 #include <vector>
 #include <cstdlib> 
 #include <string>
@@ -172,6 +173,10 @@
       _interval = interval;
     }
 
+    void setFDCallback(int fd, boost::function<void ()> callback);
+
+    void callCallback(int fd);
+
     /// Return the clock provided by this Gui.
     //
     /// The Gui clock will be paused when the gui is put
@@ -505,6 +510,11 @@
         std::exit(EXIT_SUCCESS);
     }
 
+    virtual bool watchFD(int /* fd */)
+    {
+        log_unimpl("This GUI does not implement FD watching.");
+    }
+
 
     /// Determines if playback should restart after the movie ends.
     bool            _loop;
@@ -557,6 +567,8 @@
     virtual void playHook() {}
 
 private:
+    std::map<int /* fd */, boost::function<void ()> > _fd_callbacks;
+
     /// Width of a window pixel, in stage pseudopixel units.
     float _xscale;
 

=== modified file 'plugin/plugin.cpp'
--- a/plugin/plugin.cpp 2010-01-11 06:41:38 +0000
+++ b/plugin/plugin.cpp 2010-03-16 18:04:59 +0000
@@ -411,6 +411,7 @@
     _width(0),
     _height(0),
     _streamfd(-1),
+    _controlfd(-1),
     _ichan(0),
     _ichanWatchId(0),
     _childpid(0),
@@ -467,6 +468,17 @@
             << " should be unlinked!" << std::endl;
 #endif
     }
+
+    if (_childpid > 0) {
+        // When the child has terminated (signaled by _controlfd), it remains
+        // as a defunct process and we remove it from the kernel table now.
+        int status;
+        waitpid(_childpid, &status, 0);
+#if GNASH_PLUGIN_DEBUG > 1
+        std::cout << "Child process exited with status " << status << 
std::endl;    
+#endif
+    }
+    _childpid = 0;
 }
 
 /// \brief Initialize an instance of the plugin object
@@ -509,21 +521,14 @@
     std::cout << "Gnash plugin shutting down" << std::endl;
 #endif
 
-    if (_childpid > 0) {
-        // it seems that waiting after a SIGINT hangs firefox
-        // IFF not run from the console (see bug#17082).
-        // SIGTERM instead solves this problem
-        kill(_childpid, SIGTERM);
-        int status;
-        waitpid(_childpid, &status, 0);
+    int ret = close(_controlfd);
 #if GNASH_PLUGIN_DEBUG > 1
-        std::cout << "Child process exited with status " << status << 
std::endl;    
-#endif
+    if (ret != 0) {
+        std::cout << "Gnash plugin failed to close the control socket!"
+                  << std::endl;
     }
-
-    _childpid = 0;
+#endif
 }
-
 /// \brief Set the window to be used to render in
 ///
 /// This sets up the window the plugin is supposed to render
@@ -1165,6 +1170,7 @@
     // 0 For reading, 1 for writing.
     int p2c_pipe[2];
     int c2p_pipe[2];
+    int p2c_controlpipe[2];
     
     int ret = pipe(p2c_pipe);
     if (ret == -1) {
@@ -1183,17 +1189,29 @@
 #endif
     }
 
+    ret = pipe(p2c_controlpipe);
+    if (ret == -1) {
+#ifdef GNASH_PLUGIN_DEBUG
+        std::cout << "ERROR: child to parent pipe() failed: " << 
+            std::strerror(errno) << std::endl;
+#endif
+    }
+
+    _controlfd = p2c_controlpipe[1];
+
     /*
     Setup the command line for starting Gnash
     */
 
     // Prepare width, height and window ID variables
     const size_t buf_size = 30;
-    char xid[buf_size], width[buf_size], height[buf_size], hostfd[buf_size];
+    char xid[buf_size], width[buf_size], height[buf_size], hostfd[buf_size],
+         controlfd[buf_size];
     snprintf(xid, buf_size, "%ld", win);
     snprintf(width, buf_size, "%d", _width);
     snprintf(height, buf_size, "%d", _height);
     snprintf(hostfd, buf_size, "%d", c2p_pipe[1]);
+    snprintf(controlfd, buf_size, "%d", p2c_controlpipe[0]);
 
     // Prepare Actionscript variables (e.g. Flashvars).
     std::vector<std::string> paramvalues;
@@ -1219,7 +1237,7 @@
     ADD NEW ARGUMENTS
     */ 
 
-    const size_t maxargc = 18 + paramvalues.size() * 2;
+    const size_t maxargc = 20 + paramvalues.size() * 2;
     const char **argv = new const char *[maxargc];
 
 #ifdef CREATE_STANDALONE_GNASH_LAUNCHER
@@ -1269,6 +1287,10 @@
     argv[argc++] = "-F";
     argv[argc++] = hostfd;
 
+    // Control FD
+    argv[argc++] = "-G";
+    argv[argc++] = controlfd; 
+
     // Base URL is the page that the SWF is embedded in. It is 
     // by Gnash for resolving relative URLs in the movie. If the
     // embed tag "base" is specified, its value overrides the -U
@@ -1347,6 +1369,8 @@
                                 << std::endl;
 #endif
         }
+
+        ret = close (p2c_controlpipe[0]); // close read descriptor
     
 
 #if GNASH_PLUGIN_DEBUG > 1
@@ -1360,7 +1384,7 @@
         _ichanWatchId = g_io_add_watch(_ichan, 
                 (GIOCondition)(G_IO_IN|G_IO_HUP), 
                 (GIOFunc)handlePlayerRequestsWrapper, this);
-
+        g_io_channel_unref(_ichan);
         return;
     }
 
@@ -1378,6 +1402,8 @@
 #endif
     }
 
+    ret = close(p2c_controlpipe[1]);
+
     // close standard input and direct read-fd1 to standard input
     ret = dup2 (p2c_pipe[0], fileno(stdin));
     
@@ -1399,6 +1425,8 @@
     for ( ; numfailed < 10; anfd++) {
         if ( anfd == c2p_pipe[1] ) continue; // don't close this
         if ( anfd == c2p_pipe[0] ) continue; // don't close this either 
(correct?)
+        if ( anfd == p2c_controlpipe[0] ) continue; // don't close this either 
(correct?)
+        if ( anfd == p2c_controlpipe[1] ) continue; // don't close this either 
(correct?)
         ret = close (anfd);
         if (ret < 0) {
            numfailed++;

=== modified file 'plugin/plugin.h'
--- a/plugin/plugin.h   2010-01-11 06:41:38 +0000
+++ b/plugin/plugin.h   2010-03-16 18:04:59 +0000
@@ -123,6 +123,7 @@
     int                                _streamfd;
     GIOChannel*                        _ichan;
     int                                _ichanWatchId;
+    int                                _controlfd;
     pid_t                              _childpid;
     int                                _filefd;
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]