Whitespace cleanup of libexecstream

This commit is contained in:
Ray Speth 2012-03-15 19:55:00 +00:00
parent e4f2acaf3d
commit d27066d7bd
9 changed files with 301 additions and 301 deletions

View file

@ -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);

View file

@ -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 );
};

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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();

View file

@ -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 ) ) {