Imported Upstream version 14.45.0
[platform/upstream/libzypp.git] / zypp / PluginScript.cc
index d175da2..4024bc7 100644 (file)
 
 using std::endl;
 
+#undef  ZYPP_BASE_LOGGER_LOGGROUP
+#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin"
+
 ///////////////////////////////////////////////////////////////////
 namespace zypp
 { /////////////////////////////////////////////////////////////////
 
-
   namespace
   {
-    static const char * PLUGIN_DEBUG = getenv( "ZYPP_PLUGIN_DEBUG" );
+    const char * PLUGIN_DEBUG = getenv( "ZYPP_PLUGIN_DEBUG" );
 
     /** Dump buffer string if PLUGIN_DEBUG is on.
      * \ingroup g_RAII
@@ -60,7 +62,7 @@ namespace zypp
       const std::string & _buffer;
     };
 
-    /** Dump buffer string if PLUGIN_DEBUG is on.
+    /** Dump programms stderr.
      * \ingroup g_RAII
      */
     struct PluginDumpStderr
@@ -111,7 +113,9 @@ namespace zypp
   {
     public:
       Impl( const Pathname & script_r = Pathname(), const Arguments & args_r = Arguments() )
-        : _script( script_r )
+        : _sendTimeout( _defaultSendTimeout )
+        , _receiveTimeout( _defaultReceiveTimeout )
+        , _script( script_r )
         , _args( args_r )
       {}
 
@@ -119,12 +123,13 @@ namespace zypp
       { try { close(); } catch(...) {} }
 
     public:
-      /** Timeout (sec.) when sending data. */
-      static const long send_timeout;
-      /** Timeout (sec.) when receiving data. */
-      static const long receive_timeout;
+      static long _defaultSendTimeout;
+      static long _defaultReceiveTimeout;
 
-    public:
+      long _sendTimeout;
+      long _receiveTimeout;
+
+   public:
       const Pathname & script() const
       { return _script; }
 
@@ -135,7 +140,7 @@ namespace zypp
       { return _cmd ? _cmd->getpid() : NotConnected; }
 
       bool isOpen() const
-      { return _cmd; }
+      { return _cmd != nullptr; }
 
       int lastReturn() const
       { return _lastReturn; }
@@ -164,14 +169,22 @@ namespace zypp
   /** \relates PluginScrip::Impl Stream output */
   inline std::ostream & operator<<( std::ostream & str, const PluginScript::Impl & obj )
   {
-    return dumpRangeLine( str << "PluginScript[" << obj.getPid() << "] " << obj.script(),
-                         obj.args().begin(), obj.args().end() );
+    return str << "PluginScript[" << obj.getPid() << "] " << obj.script();
   }
 
   ///////////////////////////////////////////////////////////////////
 
-  const long PluginScript::Impl::send_timeout = 3;
-  const long PluginScript::Impl::receive_timeout = 5;
+  namespace
+  {
+    const long PLUGIN_TIMEOUT =        str::strtonum<long>( getenv( "ZYPP_PLUGIN_TIMEOUT" ) );
+    const long PLUGIN_SEND_TIMEOUT =   str::strtonum<long>( getenv( "ZYPP_PLUGIN_SEND_TIMEOUT" ) );
+    const long PLUGIN_RECEIVE_TIMEOUT =        str::strtonum<long>( getenv( "ZYPP_PLUGIN_RECEIVE_TIMEOUT" ) );
+  }
+
+  long PluginScript::Impl::_defaultSendTimeout =    ( PLUGIN_SEND_TIMEOUT > 0    ? PLUGIN_SEND_TIMEOUT
+                                                                                : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
+  long PluginScript::Impl::_defaultReceiveTimeout = ( PLUGIN_RECEIVE_TIMEOUT > 0 ? PLUGIN_RECEIVE_TIMEOUT
+                                                                                : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) );
 
   ///////////////////////////////////////////////////////////////////
 
@@ -206,7 +219,7 @@ namespace zypp
     _lastReturn.reset();
     _lastExecError.clear();
 
-    DBG << *this << endl;
+    dumpRangeLine( DBG << *this, _args.begin(), _args.end() ) << endl;
   }
 
   int PluginScript::Impl::close()
@@ -214,11 +227,29 @@ namespace zypp
     if ( _cmd )
     {
       DBG << "Close:" << *this << endl;
-      _cmd->kill();
-      _lastReturn = _cmd->close();
-      _lastExecError = _cmd->execError();
-      _cmd.reset();
+      bool doKill = true;
+      try {
+       // do not kill script if _DISCONNECT is ACKed.
+       send( PluginFrame( "_DISCONNECT" ) );
+       PluginFrame ret( receive() );
+       if ( ret.isAckCommand() )
+       {
+         doKill = false;
+         str::strtonum( ret.getHeaderNT( "exit" ), _lastReturn.get() );
+         _lastExecError = ret.body();
+       }
+      }
+      catch (...)
+      { /* NOP */ }
+
+      if ( doKill )
+      {
+       _cmd->kill();
+       _lastReturn = _cmd->close();
+       _lastExecError = _cmd->execError();
+      }
       DBG << *this << " -> [" << _lastReturn << "] " << _lastExecError << endl;
+      _cmd.reset();
     }
     return _lastReturn;
   }
@@ -238,7 +269,7 @@ namespace zypp
       frame_r.writeTo( datas );
       datas.str().swap( data );
     }
-    DBG << "->send " << frame_r << endl;
+    DBG << *this << " ->send " << frame_r << endl;
 
     if ( PLUGIN_DEBUG )
     {
@@ -267,7 +298,7 @@ namespace zypp
        FD_SET( fd, &wfds );
 
        struct timeval tv;
-       tv.tv_sec = send_timeout;
+       tv.tv_sec = _sendTimeout;
        tv.tv_usec = 0;
 
        int retval = select( fd+1, NULL, &wfds, NULL, &tv );
@@ -359,7 +390,7 @@ namespace zypp
            FD_SET( fd, &rfds );
 
            struct timeval tv;
-           tv.tv_sec = receive_timeout;
+           tv.tv_sec = _receiveTimeout;
            tv.tv_usec = 0;
 
            int retval = select( fd+1, &rfds, NULL, NULL, &tv );
@@ -389,10 +420,10 @@ namespace zypp
        }
       } while ( true );
     }
-    DBG << " <-read " << data.size() << endl;
+    // DBG << " <-read " << data.size() << endl;
     std::istringstream datas( data );
     PluginFrame ret( datas );
-    DBG << ret << endl;
+    DBG << *this << " <-" << ret << endl;
     return ret;
   }
 
@@ -404,6 +435,30 @@ namespace zypp
 
   const pid_t PluginScript::NotConnected( -1 );
 
+  long PluginScript::defaultSendTimeout()
+  { return Impl::_defaultSendTimeout; }
+
+  long PluginScript::defaultReceiveTimeout()
+  { return Impl::_defaultReceiveTimeout; }
+
+  void PluginScript::defaultSendTimeout( long newval_r )
+  { Impl::_defaultSendTimeout = newval_r > 0 ? newval_r : 0; }
+
+  void PluginScript::defaultReceiveTimeout( long newval_r )
+  { Impl::_defaultReceiveTimeout = newval_r > 0 ? newval_r : 0; }
+
+  long PluginScript::sendTimeout() const
+  { return _pimpl->_sendTimeout; }
+
+  long PluginScript::receiveTimeout() const
+  { return _pimpl->_receiveTimeout; }
+
+  void PluginScript::sendTimeout( long newval_r )
+  { _pimpl->_sendTimeout = newval_r > 0 ? newval_r : 0; }
+
+  void PluginScript::receiveTimeout( long newval_r )
+  { _pimpl->_receiveTimeout = newval_r > 0 ? newval_r : 0; }
+
   PluginScript::PluginScript()
     : _pimpl( new Impl )
   {}