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
const std::string & _buffer;
};
- /** Dump buffer string if PLUGIN_DEBUG is on.
+ /** Dump programms stderr.
* \ingroup g_RAII
*/
struct PluginDumpStderr
{
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 )
{}
{ 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; }
{ return _cmd ? _cmd->getpid() : NotConnected; }
bool isOpen() const
- { return _cmd; }
+ { return _cmd != nullptr; }
int lastReturn() const
{ return _lastReturn; }
/** \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 ) );
///////////////////////////////////////////////////////////////////
_lastReturn.reset();
_lastExecError.clear();
- DBG << *this << endl;
+ dumpRangeLine( DBG << *this, _args.begin(), _args.end() ) << endl;
}
int PluginScript::Impl::close()
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;
}
frame_r.writeTo( datas );
datas.str().swap( data );
}
- DBG << "->send " << frame_r << endl;
+ DBG << *this << " ->send " << frame_r << endl;
if ( PLUGIN_DEBUG )
{
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 );
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 );
}
} 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;
}
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 )
{}