Whitespace cleanup of libexecstream
This commit is contained in:
parent
e4f2acaf3d
commit
d27066d7bd
9 changed files with 301 additions and 301 deletions
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pthread.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define HELPERS_H "posix/exec-stream-helpers.h"
|
||||
#define HELPERS_CPP "posix/exec-stream-helpers.cpp"
|
||||
|
|
@ -83,7 +83,7 @@ public:
|
|||
bool full( std::size_t limit ); // limit==0 -> no limit
|
||||
|
||||
void clear();
|
||||
|
||||
|
||||
private:
|
||||
typedef std::list< buffer_t > buffers_t;
|
||||
buffers_t m_buffers;
|
||||
|
|
@ -297,7 +297,7 @@ bool exec_stream_buffer_t::send_buffer()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool exec_stream_buffer_t::send_char( char c )
|
||||
bool exec_stream_buffer_t::send_char( char c )
|
||||
{
|
||||
std::size_t write_size=1;
|
||||
bool no_more;
|
||||
|
|
@ -396,7 +396,7 @@ std::istream & exec_stream_t::err()
|
|||
return m_impl->m_err;
|
||||
}
|
||||
|
||||
void exec_stream_t::exceptions( bool enable )
|
||||
void exec_stream_t::exceptions( bool enable )
|
||||
{
|
||||
if( enable ) {
|
||||
// getline sets failbit on eof, so we should enable badbit and badbit _only_ to propagate our exceptions through iostream code.
|
||||
|
|
@ -412,8 +412,8 @@ void exec_stream_t::exceptions( bool enable )
|
|||
|
||||
// exec_stream_t::error_t
|
||||
namespace {
|
||||
|
||||
std::string int2str( unsigned long i, int base, std::size_t width )
|
||||
|
||||
std::string int2str( unsigned long i, int base, std::size_t width )
|
||||
{
|
||||
std::string s;
|
||||
s.reserve(4);
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -40,16 +40,16 @@ public:
|
|||
exec_stream_t();
|
||||
exec_stream_t( std::string const & program, std::string const & arguments );
|
||||
template< class iterator > exec_stream_t( std::string const & program, iterator args_begin, iterator args_end );
|
||||
|
||||
|
||||
~exec_stream_t();
|
||||
|
||||
enum stream_kind_t { s_in=1, s_out=2, s_err=4, s_all=s_in|s_out|s_err, s_child=8 };
|
||||
|
||||
void set_buffer_limit( int stream_kind, std::size_t size );
|
||||
|
||||
|
||||
typedef unsigned long timeout_t;
|
||||
void set_wait_timeout( int stream_kind, timeout_t milliseconds );
|
||||
|
||||
|
||||
void set_binary_mode( int stream_kind );
|
||||
void set_text_mode( int stream_kind );
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ public:
|
|||
template< class iterator > void start( std::string const & program, iterator args_begin, iterator args_end );
|
||||
void start( std::string const & program, char const * arg1, char const * arg2 ); // to compensate for damage from the previous one
|
||||
void start( std::string const & program, char * arg1, char * arg2 );
|
||||
|
||||
|
||||
bool close_in();
|
||||
bool close();
|
||||
void kill();
|
||||
|
|
@ -68,7 +68,7 @@ public:
|
|||
std::istream & err();
|
||||
|
||||
typedef unsigned long error_code_t;
|
||||
|
||||
|
||||
class error_t : public std::exception {
|
||||
public:
|
||||
error_t( std::string const & msg );
|
||||
|
|
@ -94,16 +94,16 @@ private:
|
|||
|
||||
// helpers for template member functions
|
||||
void new_impl();
|
||||
|
||||
|
||||
class next_arg_t {
|
||||
public:
|
||||
virtual ~next_arg_t()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual std::string const * next()=0;
|
||||
};
|
||||
|
||||
|
||||
template< class iterator > class next_arg_impl_t : public next_arg_t {
|
||||
public:
|
||||
next_arg_impl_t( iterator args_begin, iterator args_end )
|
||||
|
|
@ -127,7 +127,7 @@ private:
|
|||
iterator m_args_end;
|
||||
std::string m_arg;
|
||||
};
|
||||
|
||||
|
||||
void start( std::string const & program, next_arg_t & next_arg );
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -112,13 +112,13 @@ void pipe_t::open()
|
|||
m_direction=both;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// mutex_t
|
||||
mutex_t::mutex_t()
|
||||
{
|
||||
if( int code=pthread_mutex_init( &m_mutex, 0 ) ) {
|
||||
throw os_error_t( "mutex_t::mutex_t: pthread_mutex_init failed", code );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_t::~mutex_t()
|
||||
|
|
@ -191,7 +191,7 @@ void mutex_registrator_t::release_all()
|
|||
(*i)->release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// wait_result_t
|
||||
wait_result_t::wait_result_t( unsigned signaled_state, int error_code, bool timed_out )
|
||||
{
|
||||
|
|
@ -247,7 +247,7 @@ int event_t::set( unsigned bits, mutex_registrator_t * mutex_registrator )
|
|||
m_state|=bits;
|
||||
code=pthread_cond_broadcast( &m_cond );
|
||||
}
|
||||
|
||||
|
||||
int release_code=grab_mutex.release();
|
||||
if( code==0 ) {
|
||||
code=release_code;
|
||||
|
|
@ -261,7 +261,7 @@ int event_t::reset( unsigned bits, mutex_registrator_t * mutex_registrator )
|
|||
if( !grab_mutex.ok() ) {
|
||||
return grab_mutex.error_code();
|
||||
}
|
||||
m_state&=~bits;
|
||||
m_state&=~bits;
|
||||
return grab_mutex.release();
|
||||
}
|
||||
|
||||
|
|
@ -276,7 +276,7 @@ wait_result_t event_t::wait( unsigned any_bits, unsigned long timeout, mutex_reg
|
|||
if( !grab_mutex.ok() ) {
|
||||
return wait_result_t( 0, grab_mutex.error_code(), false );
|
||||
}
|
||||
|
||||
|
||||
struct timeval time_val_limit;
|
||||
gettimeofday( &time_val_limit, 0 );
|
||||
struct timespec time_limit;
|
||||
|
|
@ -286,7 +286,7 @@ wait_result_t event_t::wait( unsigned any_bits, unsigned long timeout, mutex_reg
|
|||
while( code==0 && (m_state&any_bits)==0 ) {
|
||||
code=pthread_cond_timedwait( &m_cond, &m_mutex.m_mutex, &time_limit );
|
||||
}
|
||||
|
||||
|
||||
unsigned state=m_state;
|
||||
int release_code=grab_mutex.release();
|
||||
if( code==0 ) {
|
||||
|
|
@ -397,7 +397,7 @@ void thread_buffer_t::start()
|
|||
if( (code=m_thread_responce.reset( ~0u, 0 )) || (code=m_thread_responce.set( exec_stream_t::s_in, 0 )) ) {
|
||||
throw os_error_t( "thread_buffer_t::start: unable to initialize m_thread_responce event", code );
|
||||
}
|
||||
|
||||
|
||||
m_error_prefix="";
|
||||
m_error_code=0;
|
||||
|
||||
|
|
@ -469,7 +469,7 @@ void thread_buffer_t::get( exec_stream_t::stream_kind_t kind, char * dst, std::s
|
|||
if( !wait_result.ok() ) {
|
||||
throw os_error_t( "thread_buffer_t::get: wait for got_data failed", wait_result.error_code() );
|
||||
}
|
||||
|
||||
|
||||
if( wait_result.is_signaled( exec_stream_t::s_child ) ) {
|
||||
// thread stopped - no need to synchronize
|
||||
if( !buffer.empty() ) {
|
||||
|
|
@ -482,10 +482,10 @@ void thread_buffer_t::get( exec_stream_t::stream_kind_t kind, char * dst, std::s
|
|||
if( m_error_code!=0 ) {
|
||||
throw os_error_t( m_error_prefix, m_error_code );
|
||||
}
|
||||
// if terminated without error - signal eof
|
||||
// if terminated without error - signal eof
|
||||
size=0;
|
||||
no_more=true;
|
||||
}
|
||||
}
|
||||
}else if( wait_result.is_signaled( kind|eof_kind ) ) {
|
||||
// thread got some data for us - grab them
|
||||
grab_mutex_t grab_mutex( m_mutex, 0 );
|
||||
|
|
@ -505,7 +505,7 @@ void thread_buffer_t::get( exec_stream_t::stream_kind_t kind, char * dst, std::s
|
|||
if( int code=m_thread_responce.reset( kind, 0 ) ) {
|
||||
throw os_error_t( "thread_buffer_t::get: unable to reset got_data event", code );
|
||||
}
|
||||
}
|
||||
}
|
||||
// if buffer is not too long tell the thread we want more data
|
||||
std::size_t buffer_limit= kind==exec_stream_t::s_out ? m_out_buffer_limit : m_err_buffer_limit;
|
||||
if( !buffer.full( buffer_limit ) ) {
|
||||
|
|
@ -521,7 +521,7 @@ void thread_buffer_t::put( char * src, std::size_t & size, bool & no_more )
|
|||
if( !m_thread_started ) {
|
||||
throw exec_stream_t::error_t( "thread_buffer_t::put: thread was not started" );
|
||||
}
|
||||
if( m_in_closed || m_in_bad ) {
|
||||
if( m_in_closed || m_in_bad ) {
|
||||
size=0;
|
||||
no_more=true;
|
||||
return;
|
||||
|
|
@ -544,7 +544,7 @@ void thread_buffer_t::put( char * src, std::size_t & size, bool & no_more )
|
|||
// thread stopped - check for errors
|
||||
if( m_error_code!=0 ) {
|
||||
throw os_error_t( m_error_prefix, m_error_code );
|
||||
}
|
||||
}
|
||||
// if terminated without error - signal eof, since no one will ever write our data
|
||||
size=0;
|
||||
no_more=true;
|
||||
|
|
@ -557,7 +557,7 @@ void thread_buffer_t::put( char * src, std::size_t & size, bool & no_more )
|
|||
|
||||
no_more=false;
|
||||
m_in_buffer.put( src, size );
|
||||
|
||||
|
||||
// if the buffer is too long - make the next put() wait until it shrinks
|
||||
if( m_in_buffer.full( m_in_buffer_limit ) ) {
|
||||
if( int code=m_thread_responce.reset( exec_stream_t::s_in, 0 ) ) {
|
||||
|
|
@ -594,7 +594,7 @@ void mutex_cleanup( void * p )
|
|||
void * thread_buffer_t::thread_func( void * param )
|
||||
{
|
||||
thread_buffer_t * p=static_cast< thread_buffer_t * >( param );
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// ensures the thread is terminated before p get destroyed
|
||||
char * out_read_buffer=0;
|
||||
char * err_read_buffer=0;
|
||||
|
|
@ -605,11 +605,11 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
|
||||
mutex_registrator_t mutex_registrator;
|
||||
pthread_cleanup_push( mutex_cleanup, &mutex_registrator );
|
||||
|
||||
|
||||
try {
|
||||
out_read_buffer=new char[p->m_out_read_buffer_size];
|
||||
err_read_buffer=new char[p->m_err_read_buffer_size];
|
||||
|
||||
|
||||
buffer_list_t::buffer_t write_buffer;
|
||||
write_buffer.data=0;
|
||||
write_buffer.size=0;
|
||||
|
|
@ -690,7 +690,7 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
if( write_buffer.data==0 && wait_result.is_signaled( exec_stream_t::s_child ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// determine whether we want something
|
||||
if( write_buffer.data!=0 ) {
|
||||
FD_SET( p->m_in_pipe.w(), &write_fds );
|
||||
|
|
@ -720,7 +720,7 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// determine what we got
|
||||
|
||||
if( FD_ISSET( p->m_in_pipe.w(), &write_fds ) ) {
|
||||
|
|
@ -777,7 +777,7 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( FD_ISSET( p->m_err_pipe.r(), &read_fds ) ) {
|
||||
// it seemds we may read child's stderr
|
||||
int n_err_read=read( p->m_err_pipe.r(), err_read_buffer, p->m_err_read_buffer_size );
|
||||
|
|
@ -813,15 +813,15 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( in_closed && out_eof && err_eof ) {
|
||||
// have nothing more to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete[] write_buffer.data;
|
||||
|
||||
|
||||
}catch( ... ) {
|
||||
// might only be std::bad_alloc
|
||||
p->m_error_code=0;
|
||||
|
|
@ -836,7 +836,7 @@ void * thread_buffer_t::thread_func( void * param )
|
|||
p->m_error_code=code;
|
||||
p->m_error_prefix="exec_stream_t::thread_func: unable to set thread_stopped event";
|
||||
}
|
||||
|
||||
|
||||
pthread_cleanup_pop( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ public:
|
|||
m_buf=0;
|
||||
m_size=0;
|
||||
}
|
||||
|
||||
|
||||
~buf_t()
|
||||
{
|
||||
delete [] m_buf;
|
||||
|
|
@ -66,7 +66,7 @@ public:
|
|||
std::swap( this->m_buf, new_buf.m_buf );
|
||||
std::swap( this->m_size, new_buf.m_size );
|
||||
}
|
||||
|
||||
|
||||
data_t * data()
|
||||
{
|
||||
return m_buf;
|
||||
|
|
@ -76,7 +76,7 @@ public:
|
|||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
buf_t( buf_t const & );
|
||||
buf_t & operator=( buf_t const & );
|
||||
|
|
@ -107,7 +107,7 @@ class mutex_t {
|
|||
public:
|
||||
mutex_t();
|
||||
~mutex_t();
|
||||
|
||||
|
||||
private:
|
||||
pthread_mutex_t m_mutex;
|
||||
|
||||
|
|
@ -120,11 +120,11 @@ class grab_mutex_t {
|
|||
public:
|
||||
grab_mutex_t( mutex_t & mutex, class mutex_registrator_t * mutex_registrator );
|
||||
~grab_mutex_t();
|
||||
|
||||
|
||||
int release();
|
||||
bool ok();
|
||||
int error_code();
|
||||
|
||||
|
||||
private:
|
||||
pthread_mutex_t * m_mutex;
|
||||
int m_error_code;
|
||||
|
|
@ -169,13 +169,13 @@ public:
|
|||
|
||||
int set( unsigned bits, mutex_registrator_t * mutex_registrator );
|
||||
int reset( unsigned bits, mutex_registrator_t * mutex_registrator );
|
||||
|
||||
|
||||
wait_result_t wait( unsigned any_bits, unsigned long timeout, mutex_registrator_t * mutex_registrator );
|
||||
|
||||
private:
|
||||
mutex_t m_mutex;
|
||||
pthread_cond_t m_cond;
|
||||
unsigned volatile m_state;
|
||||
unsigned volatile m_state;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -200,9 +200,9 @@ public:
|
|||
private:
|
||||
static void * thread_func( void * param );
|
||||
|
||||
pthread_t m_thread;
|
||||
pthread_t m_thread;
|
||||
mutex_t m_mutex; // protecting m_in_buffer, m_out_buffer, m_err_buffer
|
||||
|
||||
|
||||
buffer_list_t m_in_buffer;
|
||||
buffer_list_t m_out_buffer;
|
||||
buffer_list_t m_err_buffer;
|
||||
|
|
@ -215,17 +215,17 @@ private:
|
|||
|
||||
bool m_thread_started; // set in start(), checked in set_xxx(), get() and put()
|
||||
bool m_in_closed; // set in close_in(), checked in put()
|
||||
|
||||
|
||||
pipe_t & m_in_pipe;
|
||||
pipe_t & m_out_pipe;
|
||||
pipe_t & m_err_pipe;
|
||||
|
||||
|
||||
unsigned long m_in_wait_timeout;
|
||||
unsigned long m_out_wait_timeout;
|
||||
unsigned long m_err_wait_timeout;
|
||||
|
||||
|
||||
unsigned long m_thread_termination_timeout;
|
||||
|
||||
|
||||
std::size_t m_in_buffer_limit;
|
||||
std::size_t m_out_buffer_limit;
|
||||
std::size_t m_err_buffer_limit;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -30,24 +30,24 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
struct exec_stream_t::impl_t {
|
||||
impl_t();
|
||||
~impl_t();
|
||||
|
||||
|
||||
void split_args( std::string const & program, std::string const & arguments );
|
||||
void split_args( std::string const & program, exec_stream_t::next_arg_t & next_arg );
|
||||
void start( std::string const & program );
|
||||
|
||||
|
||||
pid_t m_child_pid;
|
||||
int m_exit_code;
|
||||
unsigned long m_child_timeout;
|
||||
|
||||
buf_t< char > m_child_args;
|
||||
buf_t< char * > m_child_argp;
|
||||
|
||||
|
||||
pipe_t m_in_pipe;
|
||||
pipe_t m_out_pipe;
|
||||
pipe_t m_err_pipe;
|
||||
|
||||
thread_buffer_t m_thread;
|
||||
|
||||
|
||||
exec_stream_buffer_t m_in_buffer;
|
||||
exec_stream_buffer_t m_out_buffer;
|
||||
exec_stream_buffer_t m_err_buffer;
|
||||
|
|
@ -86,7 +86,7 @@ void exec_stream_t::impl_t::split_args( std::string const & program, std::string
|
|||
*args_end++=0;
|
||||
|
||||
std::string whitespace=" \t\r\n\v";
|
||||
|
||||
|
||||
std::string::size_type arg_start=arguments.find_first_not_of( whitespace );
|
||||
while( arg_start!=std::string::npos ) {
|
||||
++argc;
|
||||
|
|
@ -138,16 +138,16 @@ void exec_stream_t::impl_t::split_args( std::string const & program, exec_stream
|
|||
{
|
||||
typedef std::vector< std::size_t > arg_sizes_t;
|
||||
arg_sizes_t arg_sizes;
|
||||
|
||||
|
||||
m_child_args.new_data( program.size()+1 );
|
||||
std::string::traits_type::copy( m_child_args.data(), program.c_str(), program.size()+1 );
|
||||
arg_sizes.push_back( program.size()+1 );
|
||||
|
||||
|
||||
while( std::string const * s=next_arg.next() ) {
|
||||
m_child_args.append_data( s->c_str(), s->size()+1 );
|
||||
arg_sizes.push_back( s->size()+1 );
|
||||
}
|
||||
|
||||
|
||||
char ** argp_end=m_child_argp.new_data( arg_sizes.size()+1 );
|
||||
char * argp=m_child_args.data();
|
||||
for( arg_sizes_t::iterator i=arg_sizes.begin(); i!=arg_sizes.end(); ++i ) {
|
||||
|
|
@ -160,7 +160,7 @@ void exec_stream_t::impl_t::split_args( std::string const & program, exec_stream
|
|||
|
||||
void exec_stream_t::set_buffer_limit( int stream_kind, std::size_t size )
|
||||
{
|
||||
m_impl->m_thread.set_buffer_limit( stream_kind, size );
|
||||
m_impl->m_thread.set_buffer_limit( stream_kind, size );
|
||||
}
|
||||
|
||||
void exec_stream_t::set_wait_timeout( int stream_kind, timeout_t milliseconds )
|
||||
|
|
@ -176,7 +176,7 @@ void exec_stream_t::start( std::string const & program, std::string const & argu
|
|||
if( !close() ) {
|
||||
throw exec_stream_t::error_t( "exec_stream_t::start: previous child process has not yet terminated" );
|
||||
}
|
||||
|
||||
|
||||
m_impl->split_args( program, arguments );
|
||||
m_impl->start( program );
|
||||
}
|
||||
|
|
@ -196,10 +196,10 @@ void exec_stream_t::impl_t::start( std::string const & program )
|
|||
m_in_pipe.open();
|
||||
m_out_pipe.open();
|
||||
m_err_pipe.open();
|
||||
|
||||
|
||||
pipe_t status_pipe;
|
||||
status_pipe.open();
|
||||
|
||||
|
||||
pid_t pid=fork();
|
||||
if( pid==-1 ) {
|
||||
throw os_error_t( "exec_stream_t::start: fork failed" );
|
||||
|
|
@ -304,7 +304,7 @@ void exec_stream_t::impl_t::start( std::string const & program )
|
|||
m_in.clear();
|
||||
m_out.clear();
|
||||
m_err.clear();
|
||||
|
||||
|
||||
m_thread.set_read_buffer_size( exec_stream_t::s_out, STREAM_BUFFER_SIZE );
|
||||
m_thread.set_read_buffer_size( exec_stream_t::s_err, STREAM_BUFFER_SIZE );
|
||||
m_thread.start();
|
||||
|
|
@ -349,7 +349,7 @@ bool exec_stream_t::close()
|
|||
m_impl->m_child_pid=-1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}else {
|
||||
m_impl->m_child_pid=-1;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ public:
|
|||
|
||||
class error_t : public std::exception {
|
||||
public:
|
||||
error_t( std::string const & msg )
|
||||
error_t( std::string const & msg )
|
||||
: m_msg( msg )
|
||||
{
|
||||
}
|
||||
|
|
@ -71,16 +71,16 @@ public:
|
|||
~error_t() throw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual char const * what() const throw()
|
||||
{
|
||||
return m_msg.c_str();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::string m_msg;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
struct failure_t {
|
||||
std::string assertion;
|
||||
|
|
@ -93,15 +93,15 @@ private:
|
|||
failures_t failures;
|
||||
};
|
||||
typedef std::vector< result_t > results_t;
|
||||
|
||||
|
||||
static results_t m_results;
|
||||
static bool m_printed;
|
||||
|
||||
|
||||
struct force_print_t {
|
||||
~force_print_t();
|
||||
};
|
||||
friend struct force_print_t;
|
||||
|
||||
|
||||
static force_print_t m_force_print;
|
||||
};
|
||||
|
||||
|
|
@ -199,12 +199,12 @@ bool check_if_english_error_messages()
|
|||
std::string s;
|
||||
LPVOID buf;
|
||||
if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
0,
|
||||
1,
|
||||
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
|
||||
0,
|
||||
1,
|
||||
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
|
||||
(LPTSTR) &buf,
|
||||
0,
|
||||
0
|
||||
0
|
||||
)==0 ) {
|
||||
return false;
|
||||
}else {
|
||||
|
|
@ -332,7 +332,7 @@ int pathologic()
|
|||
int n=0;
|
||||
|
||||
char buf[1002];
|
||||
|
||||
|
||||
while( fgets( buf, sizeof( buf ), stdin )!=0 ) {
|
||||
int len=strlen( buf );
|
||||
|
||||
|
|
@ -372,10 +372,10 @@ int exit_code()
|
|||
}
|
||||
|
||||
// selection of child functions
|
||||
|
||||
|
||||
typedef int(*child_func_t)();
|
||||
|
||||
child_func_t find_child_func( std::string const & name )
|
||||
child_func_t find_child_func( std::string const & name )
|
||||
{
|
||||
typedef std::map< std::string, child_func_t > child_funcs_t;
|
||||
static child_funcs_t funcs;
|
||||
|
|
@ -426,7 +426,7 @@ void pathologic_one( exec_stream_t & exec_stream, bool expect_ok=true )
|
|||
}
|
||||
}
|
||||
|
||||
int main( int argc, char ** argv )
|
||||
int main( int argc, char ** argv )
|
||||
{
|
||||
if( argc>=3 ) {
|
||||
if( std::string( argv[1] )=="child" ) {
|
||||
|
|
@ -449,12 +449,12 @@ int main( int argc, char ** argv )
|
|||
|
||||
// do not test for specific error message text if it is not in english
|
||||
bool english_error_messages=check_if_english_error_messages();
|
||||
|
||||
|
||||
std::string program="./exec-stream-test";
|
||||
int n_failed=42;
|
||||
|
||||
// the tests begin here
|
||||
|
||||
|
||||
try {
|
||||
|
||||
{
|
||||
|
|
@ -465,14 +465,14 @@ int main( int argc, char ** argv )
|
|||
TEST( read_all( exec_stream.err() )=="" );
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "helloworld" );
|
||||
exec_stream_t exec_stream( program, "child helloworld" );
|
||||
TEST( read_all( exec_stream.out() )=="hello\nworld" );
|
||||
TEST( read_all( exec_stream.err() )=="" );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "helloworld binary read" );
|
||||
exec_stream_t exec_stream;
|
||||
|
|
@ -485,14 +485,14 @@ int main( int argc, char ** argv )
|
|||
#endif
|
||||
TEST( read_all( exec_stream.err() )=="" );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "hello->out world->err" );
|
||||
exec_stream_t exec_stream( program, "child hello-o-world-e" );
|
||||
TEST( read_all( exec_stream.out() )=="hello" );
|
||||
TEST( read_all( exec_stream.err() )=="world" );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "hello->out world->err read reversed" );
|
||||
exec_stream_t exec_stream( program, "child hello-o-world-e" );
|
||||
|
|
@ -512,7 +512,7 @@ int main( int argc, char ** argv )
|
|||
// do not read, leave all in buffers
|
||||
|
||||
exec_stream.start( program, "child hello-o-world-e" );
|
||||
|
||||
|
||||
TEST( read_all( exec_stream.out() )=="hello" );
|
||||
TEST( read_all( exec_stream.err() )=="world" );
|
||||
|
||||
|
|
@ -524,11 +524,11 @@ int main( int argc, char ** argv )
|
|||
TEST( s=="hello" );
|
||||
|
||||
exec_stream.start( program, "child hello-o-world-e" );
|
||||
|
||||
|
||||
TEST( read_all( exec_stream.out() )=="hello" );
|
||||
TEST( read_all( exec_stream.err() )=="world" );
|
||||
|
||||
TEST( exec_stream.close() );
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -559,13 +559,13 @@ int main( int argc, char ** argv )
|
|||
}
|
||||
TEST( !exec_stream.close() );
|
||||
exec_stream.kill();
|
||||
|
||||
|
||||
exec_stream.set_wait_timeout( exec_stream_t::s_out, 12000 );
|
||||
exec_stream.start( program, "child write-after-pause" );
|
||||
std::string s;
|
||||
std::getline( exec_stream.out(), s );
|
||||
TEST( s=="after pause" );
|
||||
|
||||
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
|
|
@ -574,7 +574,7 @@ int main( int argc, char ** argv )
|
|||
exec_stream_t exec_stream;
|
||||
exec_stream.set_wait_timeout( exec_stream_t::s_err, 15000 );
|
||||
std::string in_s=random_string( 20000 )+"\n";
|
||||
|
||||
|
||||
exec_stream.start( program, "child read-after-pause" );
|
||||
exec_stream.in()<<in_s;
|
||||
std::string s;
|
||||
|
|
@ -595,7 +595,7 @@ int main( int argc, char ** argv )
|
|||
}
|
||||
TEST( !exec_stream.close() );
|
||||
exec_stream.kill();
|
||||
|
||||
|
||||
exec_stream.set_wait_timeout( exec_stream_t::s_in, 15000 );
|
||||
exec_stream.start( program, "child read-after-pause" );
|
||||
exec_stream.in()<<in_s;
|
||||
|
|
@ -603,7 +603,7 @@ int main( int argc, char ** argv )
|
|||
TEST( s=="OK" );
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "dont read" );
|
||||
exec_stream_t exec_stream;
|
||||
|
|
@ -615,8 +615,8 @@ int main( int argc, char ** argv )
|
|||
}catch( std::exception const & e ) {
|
||||
std::string m=e.what();
|
||||
if( english_error_messages ) {
|
||||
TEST( m.find( "Broken pipe" )!=std::string::npos
|
||||
|| m.find( "pipe is being closed" )!=std::string::npos
|
||||
TEST( m.find( "Broken pipe" )!=std::string::npos
|
||||
|| m.find( "pipe is being closed" )!=std::string::npos
|
||||
|| m.find( "pipe has been ended" )!=std::string::npos );
|
||||
}
|
||||
}
|
||||
|
|
@ -625,10 +625,10 @@ int main( int argc, char ** argv )
|
|||
{
|
||||
TEST_NAME( "dont stop" );
|
||||
exec_stream_t exec_stream;
|
||||
|
||||
|
||||
// on slow machines when child hogs CPU, this may take a while
|
||||
exec_stream.set_wait_timeout( exec_stream_t::s_child, 5000 );
|
||||
|
||||
|
||||
exec_stream.start( program, "child dont-stop" );
|
||||
exec_stream.in()<<random_string( 20000 );
|
||||
TEST( !exec_stream.close() );
|
||||
|
|
@ -639,7 +639,7 @@ int main( int argc, char ** argv )
|
|||
TEST( read_all( exec_stream.err() )=="" );
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "echo-size" );
|
||||
exec_stream_t exec_stream;
|
||||
|
|
@ -695,57 +695,57 @@ int main( int argc, char ** argv )
|
|||
{
|
||||
TEST_NAME( "echo-picky" );
|
||||
exec_stream_t exec_stream;
|
||||
|
||||
|
||||
// disable exceptions while reading/writing
|
||||
exec_stream.in().exceptions( std::ios_base::goodbit );
|
||||
exec_stream.out().exceptions( std::ios_base::goodbit );
|
||||
exec_stream.err().exceptions( std::ios_base::goodbit );
|
||||
|
||||
|
||||
exec_stream.start( program, "child echo-picky" );
|
||||
std::string in_s;
|
||||
std::string out_s;
|
||||
|
||||
|
||||
in_s=random_string( 4096 );
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( in_s==out_s );
|
||||
|
||||
|
||||
in_s="ZZZZZ";
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( in_s==out_s );
|
||||
|
||||
|
||||
in_s="STOP";
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( !std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( out_s=="" );
|
||||
|
||||
|
||||
TEST( std::getline( exec_stream.err(), out_s ).good() );
|
||||
TEST( out_s=="OK" );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "echo-picky with exceptions" );
|
||||
exec_stream_t exec_stream;
|
||||
exec_stream.start( program, "child echo-picky" );
|
||||
std::string in_s;
|
||||
std::string out_s;
|
||||
|
||||
|
||||
in_s=random_string( 4096 );
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( in_s==out_s );
|
||||
|
||||
|
||||
in_s="ZZZZZ";
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( in_s==out_s );
|
||||
|
||||
|
||||
in_s="STOP";
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
TEST( !std::getline( exec_stream.out(), out_s ).good() );
|
||||
TEST( out_s=="" );
|
||||
|
||||
|
||||
TEST( std::getline( exec_stream.err(), out_s ).good() );
|
||||
TEST( out_s=="OK" );
|
||||
}
|
||||
|
|
@ -756,10 +756,10 @@ int main( int argc, char ** argv )
|
|||
exec_stream.start( program, "child echo-picky" );
|
||||
std::string in_s;
|
||||
std::string out_s;
|
||||
|
||||
|
||||
in_s="STOP";
|
||||
exec_stream.in()<<in_s<<"\n";
|
||||
|
||||
|
||||
TEST( std::getline( exec_stream.err(), out_s ).good() );
|
||||
TEST( out_s=="OK" );
|
||||
}
|
||||
|
|
@ -773,11 +773,11 @@ int main( int argc, char ** argv )
|
|||
exec_stream.err().exceptions( std::ios_base::goodbit );
|
||||
// on slow machines this test may take quite a while
|
||||
exec_stream.set_wait_timeout( exec_stream_t::s_in|exec_stream_t::s_out|exec_stream_t::s_err, 60000 );
|
||||
|
||||
|
||||
exec_stream.start( program, "child pathologic" );
|
||||
pathologic_one( exec_stream );
|
||||
TEST( exec_stream.close() );
|
||||
|
||||
|
||||
exec_stream.set_buffer_limit( exec_stream_t::s_in, 500 );
|
||||
exec_stream.start( program, "child pathologic" );
|
||||
pathologic_one( exec_stream );
|
||||
|
|
@ -785,7 +785,7 @@ int main( int argc, char ** argv )
|
|||
}
|
||||
|
||||
if( !skip_long_tests ) {
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "pathologic with exceptions" );
|
||||
exec_stream_t exec_stream;
|
||||
|
|
@ -839,7 +839,7 @@ int main( int argc, char ** argv )
|
|||
}
|
||||
TEST( exec_stream.close() );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "long out line" );
|
||||
exec_stream_t exec_stream;
|
||||
|
|
@ -857,7 +857,7 @@ int main( int argc, char ** argv )
|
|||
{
|
||||
TEST_NAME( "exit code" );
|
||||
exec_stream_t exec_stream;
|
||||
|
||||
|
||||
exec_stream.start( program, "child exit-code" );
|
||||
exec_stream.in()<<"2\n";
|
||||
TEST( exec_stream.close() );
|
||||
|
|
@ -873,14 +873,14 @@ int main( int argc, char ** argv )
|
|||
TEST_NAME( "args" );
|
||||
exec_stream_t exec_stream;
|
||||
std::string s;
|
||||
|
||||
|
||||
exec_stream.start( program, "args \"one two\" three" );
|
||||
TEST( std::getline( exec_stream.out(), s ).good() );
|
||||
TEST( s=="one two" );
|
||||
TEST( std::getline( exec_stream.out(), s ).good() );
|
||||
TEST( s=="three" );
|
||||
TEST( !std::getline( exec_stream.out(), s ).good() );
|
||||
|
||||
|
||||
exec_stream.start( program, "args -e \"print \\\"hello world\\\";\"" );
|
||||
TEST( std::getline( exec_stream.out(), s ).good() );
|
||||
TEST( s=="-e" );
|
||||
|
|
@ -895,7 +895,7 @@ int main( int argc, char ** argv )
|
|||
TEST( std::getline( exec_stream.out(), s ).good() );
|
||||
TEST( s=="three" );
|
||||
TEST( !std::getline( exec_stream.out(), s ).good() );
|
||||
|
||||
|
||||
std::vector< std::string > args2;
|
||||
args2.push_back( "args" );
|
||||
args2.push_back( "-e" );
|
||||
|
|
@ -916,7 +916,7 @@ int main( int argc, char ** argv )
|
|||
TEST( s=="zzzz" );
|
||||
TEST( !std::getline( exec_stream.out(), s ).good() );
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
TEST_NAME( "run unexistent program" );
|
||||
std::string prog="don't know what";
|
||||
|
|
@ -939,6 +939,6 @@ int main( int argc, char ** argv )
|
|||
}catch( ... ) {
|
||||
std::cerr<<"unknown exception\n";
|
||||
}
|
||||
|
||||
|
||||
return n_failed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -43,12 +43,12 @@ void os_error_t::compose( std::string const & msg, exec_stream_t::error_code_t c
|
|||
s+='\n';
|
||||
LPVOID buf;
|
||||
if( FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
0,
|
||||
code,
|
||||
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
|
||||
0,
|
||||
code,
|
||||
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
|
||||
(LPTSTR) &buf,
|
||||
0,
|
||||
0
|
||||
0
|
||||
)==0 ) {
|
||||
s+="[unable to retrieve error description]";
|
||||
}else {
|
||||
|
|
@ -66,18 +66,18 @@ void os_error_t::compose( std::string const & msg, exec_stream_t::error_code_t c
|
|||
}
|
||||
|
||||
// pipe_t
|
||||
pipe_t::pipe_t()
|
||||
: m_direction( closed ), m_r( INVALID_HANDLE_VALUE ), m_w( INVALID_HANDLE_VALUE )
|
||||
pipe_t::pipe_t()
|
||||
: m_direction( closed ), m_r( INVALID_HANDLE_VALUE ), m_w( INVALID_HANDLE_VALUE )
|
||||
{
|
||||
open();
|
||||
}
|
||||
|
||||
pipe_t::~pipe_t()
|
||||
pipe_t::~pipe_t()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void pipe_t::close_r()
|
||||
void pipe_t::close_r()
|
||||
{
|
||||
if( m_direction==both || m_direction==read ) {
|
||||
if( !CloseHandle( m_r ) ) {
|
||||
|
|
@ -87,7 +87,7 @@ void pipe_t::close_r()
|
|||
}
|
||||
}
|
||||
|
||||
void pipe_t::close_w()
|
||||
void pipe_t::close_w()
|
||||
{
|
||||
if( m_direction==both || m_direction==write ) {
|
||||
if( !CloseHandle( m_w ) ) {
|
||||
|
|
@ -97,13 +97,13 @@ void pipe_t::close_w()
|
|||
}
|
||||
}
|
||||
|
||||
void pipe_t::close()
|
||||
void pipe_t::close()
|
||||
{
|
||||
close_r();
|
||||
close_w();
|
||||
}
|
||||
|
||||
void pipe_t::open()
|
||||
void pipe_t::open()
|
||||
{
|
||||
close();
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
|
|
@ -115,19 +115,19 @@ void pipe_t::open()
|
|||
m_direction=both;
|
||||
}
|
||||
|
||||
HANDLE pipe_t::r() const
|
||||
HANDLE pipe_t::r() const
|
||||
{
|
||||
return m_r;
|
||||
}
|
||||
|
||||
HANDLE pipe_t::w() const
|
||||
HANDLE pipe_t::w() const
|
||||
{
|
||||
return m_w;
|
||||
}
|
||||
|
||||
// set_stdhandle_t
|
||||
set_stdhandle_t::set_stdhandle_t( DWORD kind, HANDLE handle )
|
||||
: m_kind( kind ), m_save_handle( GetStdHandle( kind ) )
|
||||
: m_kind( kind ), m_save_handle( GetStdHandle( kind ) )
|
||||
{
|
||||
if( m_save_handle==INVALID_HANDLE_VALUE )
|
||||
throw os_error_t( "set_stdhandle_t::set_stdhandle_t: GetStdHandle() failed" );
|
||||
|
|
@ -135,7 +135,7 @@ set_stdhandle_t::set_stdhandle_t( DWORD kind, HANDLE handle )
|
|||
throw os_error_t( "set_stdhandle_t::set_stdhandle_t: SetStdHandle() failed" );
|
||||
}
|
||||
|
||||
set_stdhandle_t::~set_stdhandle_t()
|
||||
set_stdhandle_t::~set_stdhandle_t()
|
||||
{
|
||||
SetStdHandle( m_kind, m_save_handle );
|
||||
}
|
||||
|
|
@ -360,7 +360,7 @@ void thread_buffer_t::set_read_buffer_size( std::size_t size )
|
|||
m_read_buffer_size=size;
|
||||
}
|
||||
|
||||
void thread_buffer_t::start_reader_thread( HANDLE pipe )
|
||||
void thread_buffer_t::start_reader_thread( HANDLE pipe )
|
||||
{
|
||||
start_thread( pipe, dir_read );
|
||||
}
|
||||
|
|
@ -459,7 +459,7 @@ void thread_buffer_t::get( exec_stream_t::stream_kind_t, char * dst, std::size_t
|
|||
}else {
|
||||
// thread terminated and we have no more data to return - report errors, if any
|
||||
check_error( m_message_prefix, m_error_code, m_error_message );
|
||||
// if terminated without error - signal eof
|
||||
// if terminated without error - signal eof
|
||||
no_more=true;
|
||||
size=0;
|
||||
}
|
||||
|
|
@ -500,7 +500,7 @@ void thread_buffer_t::get( exec_stream_t::stream_kind_t, char * dst, std::size_t
|
|||
DWORD WINAPI thread_buffer_t::reader_thread( LPVOID param )
|
||||
{
|
||||
thread_buffer_t * p=static_cast< thread_buffer_t * >( param );
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// ensures the thread is terminated before p get destroyed
|
||||
char * read_buffer=0;
|
||||
try {
|
||||
|
|
@ -599,7 +599,7 @@ void thread_buffer_t::put( char * const src, std::size_t & size, bool & no_more
|
|||
if( !grab_mutex.ok() ) {
|
||||
check_error( "thread_buffer_t::put: wait for mutex failed", grab_mutex.error_code(), grab_mutex.error_message() );
|
||||
}
|
||||
|
||||
|
||||
// got them - put data
|
||||
no_more=false;
|
||||
if( m_translate_crlf ) {
|
||||
|
|
@ -607,7 +607,7 @@ void thread_buffer_t::put( char * const src, std::size_t & size, bool & no_more
|
|||
}else {
|
||||
m_buffer_list.put( src, size );
|
||||
}
|
||||
|
||||
|
||||
// if the buffer is too long - make the next put() wait until it shrinks
|
||||
if( m_buffer_list.full( m_buffer_limit ) ) {
|
||||
if( !m_want_data.reset() ) {
|
||||
|
|
@ -626,7 +626,7 @@ void thread_buffer_t::put( char * const src, std::size_t & size, bool & no_more
|
|||
DWORD WINAPI thread_buffer_t::writer_thread( LPVOID param )
|
||||
{
|
||||
thread_buffer_t * p=static_cast< thread_buffer_t * >( param );
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// accessing p anywhere here is safe because thread_buffer_t destructor
|
||||
// ensures the thread is terminated before p get destroyed
|
||||
try {
|
||||
buffer_list_t::buffer_t buffer;
|
||||
|
|
@ -635,7 +635,7 @@ DWORD WINAPI thread_buffer_t::writer_thread( LPVOID param )
|
|||
std::size_t buffer_offset=0;
|
||||
|
||||
while( true ) {
|
||||
// wait for got_data or destruction, ignore timeout errors
|
||||
// wait for got_data or destruction, ignore timeout errors
|
||||
// for destruction the timeout is normally expected,
|
||||
// for got data the timeout is not normally expected but tolerable (no one wants to write)
|
||||
wait_result_t wait_result=wait( p->m_got_data, p->m_stop_thread, p->m_wait_timeout );
|
||||
|
|
@ -644,9 +644,9 @@ DWORD WINAPI thread_buffer_t::writer_thread( LPVOID param )
|
|||
p->note_thread_error( "thread_buffer_t::writer_thread: wait for got_data, destruction failed", wait_result.error_code(), wait_result.error_message() );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// if no data in local buffer to write - get from p->m_buffers
|
||||
if( buffer.data==0 && wait_result.is_signaled( p->m_got_data ) ) {
|
||||
if( buffer.data==0 && wait_result.is_signaled( p->m_got_data ) ) {
|
||||
grab_mutex_t grab_mutex( p->m_mutex, p->m_wait_timeout );
|
||||
if( !grab_mutex.ok() ) {
|
||||
p->note_thread_error( "thread_buffer_t::writer_thread: wait for mutex failed", grab_mutex.error_code(), grab_mutex.error_message() );
|
||||
|
|
@ -672,12 +672,12 @@ DWORD WINAPI thread_buffer_t::writer_thread( LPVOID param )
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// see if they want us to stop, but only when all is written
|
||||
if( buffer.data==0 && wait_result.is_signaled( p->m_stop_thread ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( buffer.data!=0 ) {
|
||||
// we have buffer - write it
|
||||
DWORD written_size;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -145,7 +145,7 @@ public:
|
|||
|
||||
void get( exec_stream_t::stream_kind_t kind, char * dst, std::size_t & size, bool & no_more ); // may be called only after start_reader_thread
|
||||
void put( char * const src, std::size_t & size, bool & no_more );// may be called only after start_writer_thread
|
||||
|
||||
|
||||
bool stop_thread();
|
||||
bool abort_thread();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2004 Artem Khodush
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ struct exec_stream_t::impl_t {
|
|||
|
||||
exec_stream_t::impl_t::impl_t()
|
||||
: m_in_buffer( exec_stream_t::s_in, m_in_thread ), m_out_buffer( exec_stream_t::s_out, m_out_thread ), m_err_buffer( exec_stream_t::s_err, m_err_thread ),
|
||||
m_in( m_in_buffer ), m_out( m_out_buffer ), m_err( m_err_buffer )
|
||||
m_in( m_in_buffer ), m_out( m_out_buffer ), m_err( m_err_buffer )
|
||||
{
|
||||
m_out.tie( &m_in );
|
||||
m_err.tie( &m_in );
|
||||
|
|
@ -179,7 +179,7 @@ void exec_stream_t::start( std::string const & program, std::string const & argu
|
|||
}
|
||||
|
||||
m_impl->m_child_process=pi.hProcess;
|
||||
|
||||
|
||||
m_impl->m_in_buffer.clear();
|
||||
m_impl->m_out_buffer.clear();
|
||||
m_impl->m_err_buffer.clear();
|
||||
|
|
@ -247,12 +247,12 @@ bool exec_stream_t::close()
|
|||
if( !close_in() ) {
|
||||
// need to close child's stdin no matter what, because otherwise "usual" child will run forever
|
||||
// And before closing child's stdin the writer thread should be stopped no matter what,
|
||||
// because it may be blocked on Write to m_in_pipe, and in that case closing m_in_pipe may block.
|
||||
// because it may be blocked on Write to m_in_pipe, and in that case closing m_in_pipe may block.
|
||||
if( !m_impl->m_in_thread.abort_thread() ) {
|
||||
throw exec_stream_t::error_t( "exec_stream_t::close: waiting till in_thread stops exceeded timeout" );
|
||||
}
|
||||
// when thread is terminated abnormally, it may left child's stdin open
|
||||
// try to close it here
|
||||
// try to close it here
|
||||
CloseHandle( m_impl->m_in_pipe );
|
||||
m_impl->m_in_pipe=0;
|
||||
}
|
||||
|
|
@ -298,7 +298,7 @@ bool exec_stream_t::close()
|
|||
return m_impl->m_child_process==0;
|
||||
}
|
||||
|
||||
void exec_stream_t::kill()
|
||||
void exec_stream_t::kill()
|
||||
{
|
||||
if( m_impl->m_child_process!=0 ) {
|
||||
if( !TerminateProcess( m_impl->m_child_process, 0 ) ) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue