Merge remote-tracking branch 'upstream/master' into Issue_socket
This commit is contained in:
commit
58ef1c2c5d
63 changed files with 490 additions and 5693 deletions
19
.travis.yml
Normal file
19
.travis.yml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
language: c++
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
|
sudo: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
- echo "deb http://de.archive.ubuntu.com/ubuntu xenial main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get install --allow-unauthenticated g++ libboost-all-dev cmake libreadline-dev libssl-dev autoconf
|
||||||
|
|
||||||
|
script:
|
||||||
|
- cmake -DCMAKE_BUILD_TYPE=Debug -DBoost_USE_STATIC_LIBS=OFF .
|
||||||
|
- make -j 2
|
||||||
|
- set -o pipefail
|
||||||
|
- tests/all_tests 2>&1 | cat
|
||||||
|
|
@ -4,8 +4,6 @@
|
||||||
PROJECT( fc )
|
PROJECT( fc )
|
||||||
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.12 )
|
CMAKE_MINIMUM_REQUIRED( VERSION 2.8.12 )
|
||||||
|
|
||||||
add_compile_options(-std=c++14)
|
|
||||||
|
|
||||||
MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}")
|
MESSAGE(STATUS "Configuring project fc located in: ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
SET( CMAKE_AUTOMOC OFF )
|
SET( CMAKE_AUTOMOC OFF )
|
||||||
|
|
||||||
|
|
@ -106,15 +104,15 @@ endif ( MSVC )
|
||||||
|
|
||||||
# Configure editline
|
# Configure editline
|
||||||
if ( MSVC )
|
if ( MSVC )
|
||||||
# autoconf won't work here, hard code the defines
|
# # autoconf won't work here, hard code the defines
|
||||||
set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
|
# set( EDITLINE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline" )
|
||||||
|
#
|
||||||
file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
|
# file( GLOB EDITLINE_SOURCES "${EDITLINE_DIR}/src/editline.c" )
|
||||||
add_library( editline ${EDITLINE_SOURCES} )
|
# add_library( editline ${EDITLINE_SOURCES} )
|
||||||
|
#
|
||||||
target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
|
# target_include_directories( editline PRIVATE "${EDITLINE_DIR}" PUBLIC "${EDITLINE_DIR}/include" )
|
||||||
|
#
|
||||||
set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
|
# set_target_properties( editline PROPERTIES COMPILE_DEFINITIONS LINKER_LANGUAGE C )
|
||||||
else ( MSVC )
|
else ( MSVC )
|
||||||
include(ExternalProject)
|
include(ExternalProject)
|
||||||
if ( MINGW )
|
if ( MINGW )
|
||||||
|
|
@ -124,7 +122,7 @@ else ( MSVC )
|
||||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
|
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline --host=x86_64-w64-mingw32
|
||||||
BUILD_COMMAND make
|
BUILD_COMMAND make
|
||||||
INSTALL_COMMAND true
|
INSTALL_COMMAND true
|
||||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a
|
||||||
)
|
)
|
||||||
else ( MINGW )
|
else ( MINGW )
|
||||||
ExternalProject_Add( project_editline
|
ExternalProject_Add( project_editline
|
||||||
|
|
@ -133,7 +131,7 @@ else ( MSVC )
|
||||||
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/vendor/editline/configure --prefix=${CMAKE_CURRENT_BINARY_DIR}/vendor/editline
|
||||||
BUILD_COMMAND make
|
BUILD_COMMAND make
|
||||||
INSTALL_COMMAND true
|
INSTALL_COMMAND true
|
||||||
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/.libs/libeditline.a
|
BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/vendor/editline/src/project_editline-build/src/.libs/libeditline.a
|
||||||
)
|
)
|
||||||
endif ( MINGW )
|
endif ( MINGW )
|
||||||
ExternalProject_Add_Step(project_editline autogen
|
ExternalProject_Add_Step(project_editline autogen
|
||||||
|
|
@ -223,6 +221,7 @@ set( fc_sources
|
||||||
src/asio.cpp
|
src/asio.cpp
|
||||||
src/string.cpp
|
src/string.cpp
|
||||||
src/shared_ptr.cpp
|
src/shared_ptr.cpp
|
||||||
|
src/stacktrace.cpp
|
||||||
src/time.cpp
|
src/time.cpp
|
||||||
src/utf8.cpp
|
src/utf8.cpp
|
||||||
src/io/iostream.cpp
|
src/io/iostream.cpp
|
||||||
|
|
@ -234,7 +233,6 @@ set( fc_sources
|
||||||
src/io/varint.cpp
|
src/io/varint.cpp
|
||||||
src/io/console.cpp
|
src/io/console.cpp
|
||||||
src/filesystem.cpp
|
src/filesystem.cpp
|
||||||
src/interprocess/process.cpp
|
|
||||||
src/interprocess/signals.cpp
|
src/interprocess/signals.cpp
|
||||||
src/interprocess/file_mapping.cpp
|
src/interprocess/file_mapping.cpp
|
||||||
src/interprocess/mmap_struct.cpp
|
src/interprocess/mmap_struct.cpp
|
||||||
|
|
@ -302,8 +300,10 @@ setup_library( fc SOURCES ${sources} LIBRARY_TYPE STATIC )
|
||||||
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/include/" DESTINATION include )
|
||||||
|
|
||||||
# begin editline stuff
|
# begin editline stuff
|
||||||
|
if(NOT MSVC)
|
||||||
target_compile_definitions (fc PRIVATE HAVE_EDITLINE)
|
target_compile_definitions (fc PRIVATE HAVE_EDITLINE)
|
||||||
set(editline_libraries editline)
|
set(editline_libraries editline)
|
||||||
|
endif(NOT MSVC)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
target_compile_definitions( fc PRIVATE _CRT_NONSTDC_NO_DEPRECATE )
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
@ -403,7 +403,6 @@ target_include_directories(fc
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp
|
||||||
|
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/boost_1.51/include
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
${CMAKE_CURRENT_SOURCE_DIR}/vendor/secp256k1-zkp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
fc
|
fc
|
||||||
==
|
==
|
||||||
|
|
||||||
|
[](https://travis-ci.org/bitshares/bitshares-fc)
|
||||||
|
|
||||||
**NOTE:** This fork reverts upstream commit a421e280488385cab26a42153f7ce3c8d5b6281f to avoid changing the BitShares API.
|
**NOTE:** This fork reverts upstream commit a421e280488385cab26a42153f7ce3c8d5b6281f to avoid changing the BitShares API.
|
||||||
|
|
||||||
FC stands for fast-compiling c++ library and provides a set of utility libraries useful
|
FC stands for fast-compiling c++ library and provides a set of utility libraries useful
|
||||||
|
|
|
||||||
|
|
@ -133,16 +133,5 @@ namespace std
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
template<>
|
|
||||||
struct hash<fc::sha256>
|
|
||||||
{
|
|
||||||
size_t operator()( const fc::sha256& s )const
|
|
||||||
{
|
|
||||||
return s._hash[3];//*((size_t*)&s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#include <fc/reflect/reflect.hpp>
|
#include <fc/reflect/reflect.hpp>
|
||||||
FC_REFLECT_TYPENAME( fc::sha256 )
|
FC_REFLECT_TYPENAME( fc::sha256 )
|
||||||
|
|
|
||||||
|
|
@ -159,5 +159,7 @@ FC_REFLECT_TYPENAME( fc::log_message );
|
||||||
* @param ... A set of key/value pairs denoted as ("key",val)("key2",val2)...
|
* @param ... A set of key/value pairs denoted as ("key",val)("key2",val2)...
|
||||||
*/
|
*/
|
||||||
#define FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, ... ) \
|
#define FC_LOG_MESSAGE( LOG_LEVEL, FORMAT, ... ) \
|
||||||
fc::log_message( FC_LOG_CONTEXT(LOG_LEVEL), FORMAT, fc::limited_mutable_variant_object(FC_MAX_LOG_OBJECT_DEPTH)__VA_ARGS__ )
|
fc::log_message( FC_LOG_CONTEXT(LOG_LEVEL), \
|
||||||
|
FORMAT, \
|
||||||
|
fc::limited_mutable_variant_object( FC_MAX_LOG_OBJECT_DEPTH, true )__VA_ARGS__ )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -156,12 +156,39 @@ namespace fc
|
||||||
#define FC_FORMAT_ARG_PARAMS( ... )\
|
#define FC_FORMAT_ARG_PARAMS( ... )\
|
||||||
BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, __VA_ARGS__ )
|
BOOST_PP_SEQ_FOR_EACH( FC_FORMAT_ARGS, v, __VA_ARGS__ )
|
||||||
|
|
||||||
|
#define FC_DUMP_FORMAT_ARG_NAME(r, unused, base) \
|
||||||
|
"(" BOOST_PP_STRINGIZE(base) ")"
|
||||||
|
|
||||||
|
#define FC_DUMP_FORMAT_ARG_NAMES( SEQ )\
|
||||||
|
BOOST_PP_SEQ_FOR_EACH( FC_DUMP_FORMAT_ARG_NAME, v, SEQ )
|
||||||
|
|
||||||
|
// TODO FC_FORMAT_ARG_PARAMS(...) may throw exceptions when calling fc::variant(...) inside,
|
||||||
|
// as a quick-fix / workaround, we catch all exceptions here.
|
||||||
|
// However, to log as much info as possible, it's better to catch exceptions when processing each argument
|
||||||
#define idump( SEQ ) \
|
#define idump( SEQ ) \
|
||||||
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
|
{ \
|
||||||
|
try { \
|
||||||
|
ilog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
|
||||||
|
} catch( ... ) { \
|
||||||
|
ilog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
#define wdump( SEQ ) \
|
#define wdump( SEQ ) \
|
||||||
wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
|
{ \
|
||||||
|
try { \
|
||||||
|
wlog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
|
||||||
|
} catch( ... ) { \
|
||||||
|
wlog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
#define edump( SEQ ) \
|
#define edump( SEQ ) \
|
||||||
elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) )
|
{ \
|
||||||
|
try { \
|
||||||
|
elog( FC_FORMAT(SEQ), FC_FORMAT_ARG_PARAMS(SEQ) ); \
|
||||||
|
} catch( ... ) { \
|
||||||
|
elog ( "[ERROR: Got exception while trying to dump ( ${args} )]",("args",FC_DUMP_FORMAT_ARG_NAMES(SEQ)) ); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
// this disables all normal logging statements -- not something you'd normally want to do,
|
// this disables all normal logging statements -- not something you'd normally want to do,
|
||||||
// but it's useful if you're benchmarking something and suspect logging is causing
|
// but it's useful if you're benchmarking something and suspect logging is causing
|
||||||
|
|
|
||||||
16
include/fc/stacktrace.hpp
Normal file
16
include/fc/stacktrace.hpp
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
// stacktrace.h (c) 2008, Timo Bingmann from http://idlebox.net/
|
||||||
|
// published under the WTFPL v2.0
|
||||||
|
|
||||||
|
// Downloaded from http://panthema.net/2008/0901-stacktrace-demangled/
|
||||||
|
// and modified for C++ and FC by Steemit, Inc.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace fc {
|
||||||
|
|
||||||
|
void print_stacktrace(std::ostream& out);
|
||||||
|
void print_stacktrace_on_segfault();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -211,6 +211,9 @@ namespace fc
|
||||||
variant( uint32_t val, uint32_t max_depth = 1 );
|
variant( uint32_t val, uint32_t max_depth = 1 );
|
||||||
variant( int32_t val, uint32_t max_depth = 1 );
|
variant( int32_t val, uint32_t max_depth = 1 );
|
||||||
variant( uint64_t val, uint32_t max_depth = 1 );
|
variant( uint64_t val, uint32_t max_depth = 1 );
|
||||||
|
#ifdef __APPLE__
|
||||||
|
variant( size_t val, uint32_t max_depth = 1 );
|
||||||
|
#endif
|
||||||
variant( int64_t val, uint32_t max_depth = 1 );
|
variant( int64_t val, uint32_t max_depth = 1 );
|
||||||
variant( double val, uint32_t max_depth = 1 );
|
variant( double val, uint32_t max_depth = 1 );
|
||||||
variant( bool val, uint32_t max_depth = 1 );
|
variant( bool val, uint32_t max_depth = 1 );
|
||||||
|
|
@ -561,7 +564,7 @@ namespace fc
|
||||||
to_variant( val, *this, max_depth );
|
to_variant( val, *this, max_depth );
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
inline void to_variant( size_t s, variant& v, uint32_t max_depth = 1 ) { v = variant(uint64_t(s)); }
|
inline void to_variant( size_t s, variant& v, uint32_t max_depth ) { v = variant(uint64_t(s)); }
|
||||||
#endif
|
#endif
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void to_variant( const std::shared_ptr<T>& var, variant& vo, uint32_t max_depth )
|
void to_variant( const std::shared_ptr<T>& var, variant& vo, uint32_t max_depth )
|
||||||
|
|
|
||||||
|
|
@ -221,18 +221,35 @@ namespace fc
|
||||||
class limited_mutable_variant_object : public mutable_variant_object
|
class limited_mutable_variant_object : public mutable_variant_object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
limited_mutable_variant_object( uint32_t max_depth );
|
limited_mutable_variant_object( uint32_t max_depth, bool skip_on_exception = false );
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
limited_mutable_variant_object& operator()( string key, T&& var )
|
limited_mutable_variant_object& operator()( string key, T&& var )
|
||||||
{
|
{
|
||||||
set( std::move(key), variant( fc::forward<T>(var), _max_depth ) );
|
if( _reached_depth_limit )
|
||||||
|
// _skip_on_exception will always be true here
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
optional<variant> v;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
v = variant( fc::forward<T>(var), _max_depth );
|
||||||
|
}
|
||||||
|
catch( ... )
|
||||||
|
{
|
||||||
|
if( !_skip_on_exception )
|
||||||
|
throw;
|
||||||
|
v = variant( "[ERROR: Caught exception while converting data to variant]" );
|
||||||
|
}
|
||||||
|
set( std::move(key), *v );
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
limited_mutable_variant_object& operator()( const variant_object& vo );
|
limited_mutable_variant_object& operator()( const variant_object& vo );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint32_t _max_depth;
|
const uint32_t _max_depth; ///< The depth limit
|
||||||
|
const bool _reached_depth_limit; ///< Indicates whether we've reached depth limit
|
||||||
|
const bool _skip_on_exception; ///< If set to true, won't rethrow exceptions when reached depth limit
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @ingroup Serializable */
|
/** @ingroup Serializable */
|
||||||
|
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
#include <fc/interprocess/process.hpp>
|
|
||||||
#include <fc/io/iostream.hpp>
|
|
||||||
#include <fc/io/buffered_iostream.hpp>
|
|
||||||
#include <fc/asio.hpp>
|
|
||||||
#include <fc/filesystem.hpp>
|
|
||||||
#include <fc/log/logger.hpp>
|
|
||||||
#include <boost/process/all.hpp>
|
|
||||||
#include <boost/iostreams/stream.hpp>
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
namespace fc {
|
|
||||||
namespace bp = boost::process;
|
|
||||||
namespace io = boost::iostreams;
|
|
||||||
|
|
||||||
fc::path find_executable_in_path( const fc::string name ) {
|
|
||||||
try {
|
|
||||||
return fc::string(bp::find_executable_in_path( std::string(name), "" ));
|
|
||||||
} catch (...) {
|
|
||||||
const char* p = std::getenv("PATH");
|
|
||||||
FC_THROW( "Unable to find executable ${exe} in path.",
|
|
||||||
("exe", name)
|
|
||||||
("inner", fc::except_str() )
|
|
||||||
("PATH", fc::string(p!=nullptr?p:"") ) );
|
|
||||||
}
|
|
||||||
return fc::path();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class process::impl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
impl()
|
|
||||||
:stat( fc::asio::default_io_service() ){}
|
|
||||||
|
|
||||||
~impl()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if( _in )
|
|
||||||
{
|
|
||||||
_in->close();
|
|
||||||
}
|
|
||||||
if( _exited.valid() && !_exited.ready())
|
|
||||||
{
|
|
||||||
//child->terminate();
|
|
||||||
_exited.wait();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
wlog( "caught exception cleaning up process: ${except_str}", ("except_str",fc::except_str()) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<bp::child> child;
|
|
||||||
|
|
||||||
std::shared_ptr<bp::pipe> _inp;
|
|
||||||
std::shared_ptr<bp::pipe> _outp;
|
|
||||||
std::shared_ptr<bp::pipe> _errp;
|
|
||||||
|
|
||||||
buffered_istream_ptr _out;
|
|
||||||
buffered_istream_ptr _err;
|
|
||||||
buffered_ostream_ptr _in;
|
|
||||||
|
|
||||||
bp::status stat;
|
|
||||||
bp::context pctx;
|
|
||||||
|
|
||||||
fc::future<int> _exited;
|
|
||||||
};
|
|
||||||
|
|
||||||
process::process()
|
|
||||||
:my( new process::impl() ){}
|
|
||||||
process::~process(){}
|
|
||||||
|
|
||||||
iprocess& process::exec( const fc::path& exe,
|
|
||||||
std::vector<std::string> args,
|
|
||||||
const fc::path& work_dir, int opt )
|
|
||||||
{
|
|
||||||
|
|
||||||
my->pctx.work_dir = work_dir.string();
|
|
||||||
my->pctx.suppress_console = (opt & suppress_console) != 0;
|
|
||||||
|
|
||||||
if( opt&open_stdout)
|
|
||||||
my->pctx.streams[boost::process::stdout_id] = bp::behavior::async_pipe();
|
|
||||||
else
|
|
||||||
my->pctx.streams[boost::process::stdout_id] = bp::behavior::null();
|
|
||||||
|
|
||||||
|
|
||||||
if( opt& open_stderr )
|
|
||||||
my->pctx.streams[boost::process::stderr_id] = bp::behavior::async_pipe();
|
|
||||||
else
|
|
||||||
my->pctx.streams[boost::process::stderr_id] = bp::behavior::null();
|
|
||||||
|
|
||||||
if( opt& open_stdin )
|
|
||||||
my->pctx.streams[boost::process::stdin_id] = bp::behavior::async_pipe();
|
|
||||||
else
|
|
||||||
my->pctx.streams[boost::process::stdin_id] = bp::behavior::close();
|
|
||||||
|
|
||||||
/*
|
|
||||||
std::vector<std::string> a;
|
|
||||||
a.reserve(size_t(args.size()));
|
|
||||||
for( uint32_t i = 0; i < args.size(); ++i ) {
|
|
||||||
a.push_back( fc::move(args[i]) );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
my->child.reset( new bp::child( bp::create_child( exe.string(), fc::move(args), my->pctx ) ) );
|
|
||||||
|
|
||||||
if( opt & open_stdout ) {
|
|
||||||
bp::handle outh = my->child->get_handle( bp::stdout_id );
|
|
||||||
my->_outp.reset( new bp::pipe( fc::asio::default_io_service(), outh.release() ) );
|
|
||||||
}
|
|
||||||
if( opt & open_stderr ) {
|
|
||||||
bp::handle errh = my->child->get_handle( bp::stderr_id );
|
|
||||||
my->_errp.reset( new bp::pipe( fc::asio::default_io_service(), errh.release() ) );
|
|
||||||
}
|
|
||||||
if( opt & open_stdin ) {
|
|
||||||
bp::handle inh = my->child->get_handle( bp::stdin_id );
|
|
||||||
my->_inp.reset( new bp::pipe( fc::asio::default_io_service(), inh.release() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
promise<int>::ptr p(new promise<int>("process"));
|
|
||||||
my->stat.async_wait( my->child->get_id(), [=]( const boost::system::error_code& ec, int exit_code )
|
|
||||||
{
|
|
||||||
//slog( "process::result %d", exit_code );
|
|
||||||
if( !ec ) {
|
|
||||||
#ifdef BOOST_POSIX_API
|
|
||||||
if( WIFEXITED(exit_code) ) p->set_value( WEXITSTATUS(exit_code) );
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p->set_exception(
|
|
||||||
fc::exception_ptr( new fc::exception(
|
|
||||||
FC_LOG_MESSAGE( error, "process exited with: ${message} ",
|
|
||||||
("message", strsignal(WTERMSIG(exit_code))) ) ) ) );
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
p->set_value(exit_code);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
p->set_exception(
|
|
||||||
fc::exception_ptr( new fc::exception(
|
|
||||||
FC_LOG_MESSAGE( error, "process exited with: ${message} ",
|
|
||||||
("message", boost::system::system_error(ec).what())) ) ) );
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if( opt & open_stdin )
|
|
||||||
my->_in = std::make_shared<buffered_ostream>(std::make_shared<fc::asio::ostream<bp::pipe>>(my->_inp));
|
|
||||||
if( opt & open_stdout )
|
|
||||||
my->_out = std::make_shared<buffered_istream>(std::make_shared<fc::asio::istream<bp::pipe>>(my->_outp));
|
|
||||||
if( opt & open_stderr )
|
|
||||||
my->_err = std::make_shared<buffered_istream>(std::make_shared<fc::asio::istream<bp::pipe>>(my->_errp));
|
|
||||||
my->_exited = p;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forcefully kills the process.
|
|
||||||
*/
|
|
||||||
void process::kill() {
|
|
||||||
my->child->terminate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns a stream that writes to the process' stdin
|
|
||||||
*/
|
|
||||||
fc::buffered_ostream_ptr process::in_stream() {
|
|
||||||
return my->_in;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief returns a stream that reads from the process' stdout
|
|
||||||
*/
|
|
||||||
fc::buffered_istream_ptr process::out_stream() {
|
|
||||||
return my->_out;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @brief returns a stream that reads from the process' stderr
|
|
||||||
*/
|
|
||||||
fc::buffered_istream_ptr process::err_stream() {
|
|
||||||
return my->_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int process::result(const microseconds& timeout /* = microseconds::maximum() */)
|
|
||||||
{
|
|
||||||
return my->_exited.wait(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ namespace fc {
|
||||||
#elif !defined(__clang__) || (__clang_major__ >= 6)
|
#elif !defined(__clang__) || (__clang_major__ >= 6)
|
||||||
// This should work for modern Linuxes and for OSX >= Mountain Lion
|
// This should work for modern Linuxes and for OSX >= Mountain Lion
|
||||||
int timeout_sec = interval.count() / fc::seconds(1).count();
|
int timeout_sec = interval.count() / fc::seconds(1).count();
|
||||||
if (setsockopt(my->_sock.native(), IPPROTO_TCP,
|
if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP,
|
||||||
#if defined( __APPLE__ )
|
#if defined( __APPLE__ )
|
||||||
TCP_KEEPALIVE,
|
TCP_KEEPALIVE,
|
||||||
#else
|
#else
|
||||||
|
|
@ -192,7 +192,7 @@ namespace fc {
|
||||||
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
||||||
wlog("Error setting TCP keepalive idle time");
|
wlog("Error setting TCP keepalive idle time");
|
||||||
# if !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9
|
# if !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9
|
||||||
if (setsockopt(my->_sock.native(), IPPROTO_TCP, TCP_KEEPINTVL,
|
if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, TCP_KEEPINTVL,
|
||||||
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
(char*)&timeout_sec, sizeof(timeout_sec)) < 0)
|
||||||
wlog("Error setting TCP keepalive interval");
|
wlog("Error setting TCP keepalive interval");
|
||||||
# endif // !__APPLE__ || TCP_KEEPINTVL
|
# endif // !__APPLE__ || TCP_KEEPINTVL
|
||||||
|
|
@ -224,7 +224,7 @@ namespace fc {
|
||||||
if (detail::have_so_reuseport)
|
if (detail::have_so_reuseport)
|
||||||
{
|
{
|
||||||
int reuseport_value = 1;
|
int reuseport_value = 1;
|
||||||
if (setsockopt(my->_sock.native(), SOL_SOCKET, SO_REUSEPORT,
|
if (setsockopt(my->_sock.native_handle(), SOL_SOCKET, SO_REUSEPORT,
|
||||||
(char*)&reuseport_value, sizeof(reuseport_value)) < 0)
|
(char*)&reuseport_value, sizeof(reuseport_value)) < 0)
|
||||||
{
|
{
|
||||||
if (errno == ENOPROTOOPT)
|
if (errno == ENOPROTOOPT)
|
||||||
|
|
@ -291,7 +291,7 @@ namespace fc {
|
||||||
if (detail::have_so_reuseport)
|
if (detail::have_so_reuseport)
|
||||||
{
|
{
|
||||||
int reuseport_value = 1;
|
int reuseport_value = 1;
|
||||||
if (setsockopt(my->_accept.native(), SOL_SOCKET, SO_REUSEPORT,
|
if (setsockopt(my->_accept.native_handle(), SOL_SOCKET, SO_REUSEPORT,
|
||||||
(char*)&reuseport_value, sizeof(reuseport_value)) < 0)
|
(char*)&reuseport_value, sizeof(reuseport_value)) < 0)
|
||||||
{
|
{
|
||||||
if (errno == ENOPROTOOPT)
|
if (errno == ENOPROTOOPT)
|
||||||
|
|
|
||||||
44
src/stacktrace.cpp
Normal file
44
src/stacktrace.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
//
|
||||||
|
// A stacktrace handler for bitshares
|
||||||
|
//
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
// only include stacktrace stuff if boost >= 1.65
|
||||||
|
#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fc/log/logger.hpp>
|
||||||
|
#include <boost/stacktrace.hpp>
|
||||||
|
|
||||||
|
namespace fc
|
||||||
|
{
|
||||||
|
|
||||||
|
static void segfault_signal_handler(int signum)
|
||||||
|
{
|
||||||
|
::signal(signum, SIG_DFL);
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << boost::stacktrace::stacktrace();
|
||||||
|
elog(ss.str());
|
||||||
|
::raise(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_stacktrace_on_segfault()
|
||||||
|
{
|
||||||
|
::signal(SIGSEGV, &segfault_signal_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_stacktrace(std::ostream& out)
|
||||||
|
{
|
||||||
|
out << boost::stacktrace::stacktrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Stacktrace output requires Boost 1.65 or above.
|
||||||
|
// Therefore calls to these methods do nothing.
|
||||||
|
namespace fc
|
||||||
|
{
|
||||||
|
void print_stacktrace_on_segfault() {}
|
||||||
|
void print_stacktrace(std::ostream& out) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -74,6 +74,14 @@ variant::variant( uint64_t val, uint32_t max_depth )
|
||||||
set_variant_type( this, uint64_type );
|
set_variant_type( this, uint64_type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
variant::variant( size_t val, uint32_t max_depth )
|
||||||
|
{
|
||||||
|
*reinterpret_cast<uint64_t*>(this) = val;
|
||||||
|
set_variant_type( this, uint64_type );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
variant::variant( int64_t val, uint32_t max_depth )
|
variant::variant( int64_t val, uint32_t max_depth )
|
||||||
{
|
{
|
||||||
*reinterpret_cast<int64_t*>(this) = val;
|
*reinterpret_cast<int64_t*>(this) = val;
|
||||||
|
|
|
||||||
|
|
@ -365,15 +365,35 @@ namespace fc
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
limited_mutable_variant_object::limited_mutable_variant_object( uint32_t m )
|
limited_mutable_variant_object::limited_mutable_variant_object( uint32_t m, bool skip_on_exception )
|
||||||
: mutable_variant_object(), _max_depth(m - 1)
|
: mutable_variant_object(),
|
||||||
|
_max_depth(m - 1),
|
||||||
|
_reached_depth_limit(m == 0),
|
||||||
|
_skip_on_exception(skip_on_exception)
|
||||||
{
|
{
|
||||||
|
if( !skip_on_exception )
|
||||||
FC_ASSERT( m > 0, "Recursion depth exceeded!" );
|
FC_ASSERT( m > 0, "Recursion depth exceeded!" );
|
||||||
|
else if( m == 0 )
|
||||||
|
set( "__err_msg", "[ERROR: Recusion depth exceeded!]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
limited_mutable_variant_object& limited_mutable_variant_object::operator()( const variant_object& vo )
|
limited_mutable_variant_object& limited_mutable_variant_object::operator()( const variant_object& vo )
|
||||||
|
{
|
||||||
|
if( _reached_depth_limit )
|
||||||
|
// _skip_on_exception will always be true here
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
mutable_variant_object::operator()( vo );
|
mutable_variant_object::operator()( vo );
|
||||||
|
}
|
||||||
|
catch( ... )
|
||||||
|
{
|
||||||
|
if( !_skip_on_exception )
|
||||||
|
throw;
|
||||||
|
else
|
||||||
|
set( "__err_msg", "[ERROR: Caught exception in operator()( const variant_object& ).]" );
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,9 @@ add_executable( all_tests all_tests.cpp
|
||||||
bloom_test.cpp
|
bloom_test.cpp
|
||||||
real128_test.cpp
|
real128_test.cpp
|
||||||
serialization_test.cpp
|
serialization_test.cpp
|
||||||
|
stacktrace_test.cpp
|
||||||
time_test.cpp
|
time_test.cpp
|
||||||
utf8_test.cpp
|
utf8_test.cpp
|
||||||
|
variant_test.cpp
|
||||||
)
|
)
|
||||||
target_link_libraries( all_tests fc )
|
target_link_libraries( all_tests fc )
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,9 @@ static void check_randomness( const char* buffer, size_t len ) {
|
||||||
double variance = (E - 1) * (E - 2) / (oc + zc - 1);
|
double variance = (E - 1) * (E - 2) / (oc + zc - 1);
|
||||||
double sigma = sqrt(variance);
|
double sigma = sqrt(variance);
|
||||||
|
|
||||||
BOOST_CHECK_GT(rc, E - sigma);
|
// Next 2 test were removed as it will not always pass
|
||||||
BOOST_CHECK_LT(rc, E + sigma);
|
//BOOST_CHECK_GT(rc, E - sigma);
|
||||||
|
//BOOST_CHECK_LT(rc, E + sigma);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE(fc_crypto)
|
BOOST_AUTO_TEST_SUITE(fc_crypto)
|
||||||
|
|
|
||||||
|
|
@ -231,8 +231,8 @@ BOOST_AUTO_TEST_CASE(structured_test)
|
||||||
fc::variant v_uint64_1( (int8_t) 1 );
|
fc::variant v_uint64_1( (int8_t) 1 );
|
||||||
fc::variant v_float_1( 0.0f );
|
fc::variant v_float_1( 0.0f );
|
||||||
fc::variant v_float_2( -2.0f );
|
fc::variant v_float_2( -2.0f );
|
||||||
fc::variant v_double_1( 0.0d );
|
fc::variant v_double_1( 0.0 );
|
||||||
fc::variant v_double_2( -2.0d );
|
fc::variant v_double_2( -2.0 );
|
||||||
fc::variants v_small_array
|
fc::variants v_small_array
|
||||||
{
|
{
|
||||||
v_empty_obj,
|
v_empty_obj,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ BOOST_AUTO_TEST_CASE(websocket_test)
|
||||||
{
|
{
|
||||||
fc::http::websocket_client client;
|
fc::http::websocket_client client;
|
||||||
fc::http::websocket_connection_ptr s_conn, c_conn;
|
fc::http::websocket_connection_ptr s_conn, c_conn;
|
||||||
|
int port;
|
||||||
{
|
{
|
||||||
fc::http::websocket_server server;
|
fc::http::websocket_server server;
|
||||||
server.on_connection([&]( const fc::http::websocket_connection_ptr& c ){
|
server.on_connection([&]( const fc::http::websocket_connection_ptr& c ){
|
||||||
|
|
@ -19,11 +20,26 @@ BOOST_AUTO_TEST_CASE(websocket_test)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen( 8090 );
|
bool listen_ok = false;
|
||||||
|
for( int i = 0; !listen_ok && i < 5; ++i )
|
||||||
|
{
|
||||||
|
port = std::rand() % 50000 + 10000;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.listen( port );
|
||||||
|
listen_ok = true;
|
||||||
|
}
|
||||||
|
catch( std::exception )
|
||||||
|
{
|
||||||
|
// if the port is busy, listen() will throw a std::exception, do nothing here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_REQUIRE( listen_ok );
|
||||||
|
|
||||||
server.start_accept();
|
server.start_accept();
|
||||||
|
|
||||||
std::string echo;
|
std::string echo;
|
||||||
c_conn = client.connect( "ws://localhost:8090" );
|
c_conn = client.connect( "ws://localhost:" + fc::to_string(port) );
|
||||||
c_conn->on_message_handler([&](const std::string& s){
|
c_conn->on_message_handler([&](const std::string& s){
|
||||||
echo = s;
|
echo = s;
|
||||||
});
|
});
|
||||||
|
|
@ -43,7 +59,7 @@ BOOST_AUTO_TEST_CASE(websocket_test)
|
||||||
//std::cerr << e.to_string() << "\n";
|
//std::cerr << e.to_string() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
c_conn = client.connect( "ws://localhost:8090" );
|
c_conn = client.connect( "ws://localhost:" + fc::to_string(port) );
|
||||||
c_conn->on_message_handler([&](const std::string& s){
|
c_conn->on_message_handler([&](const std::string& s){
|
||||||
echo = s;
|
echo = s;
|
||||||
});
|
});
|
||||||
|
|
@ -55,17 +71,19 @@ BOOST_AUTO_TEST_CASE(websocket_test)
|
||||||
try {
|
try {
|
||||||
c_conn->send_message( "again" );
|
c_conn->send_message( "again" );
|
||||||
BOOST_FAIL("expected assertion failure");
|
BOOST_FAIL("expected assertion failure");
|
||||||
|
} catch (const fc::assert_exception& e) {
|
||||||
|
std::cerr << "Expected assertion failure : " << e.to_string() << "\n";
|
||||||
} catch (const fc::exception& e) {
|
} catch (const fc::exception& e) {
|
||||||
std::cerr << e.to_string() << "\n";
|
BOOST_FAIL("Unexpected exception : " + e.to_string());
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_FAIL("Unexpected exception : " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
c_conn = client.connect( "ws://localhost:8090" );
|
c_conn = client.connect( "ws://localhost:" + fc::to_string(port) );
|
||||||
BOOST_FAIL("expected assertion failure");
|
BOOST_FAIL("expected fc::exception (fail to connect)");
|
||||||
} catch (const fc::exception& e) {
|
} catch (const fc::exception& e) {
|
||||||
std::cerr << e.to_string() << "\n";
|
std::cerr << "Excepted fc::exception : " << e.to_string() << "\n";
|
||||||
} catch (const fc::exception& e) {
|
|
||||||
BOOST_FAIL("Unexpected exception: " + e.to_string());
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
BOOST_FAIL("Unexpected exception : " + std::string(e.what()));
|
BOOST_FAIL("Unexpected exception : " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
50
tests/stacktrace_test.cpp
Normal file
50
tests/stacktrace_test.cpp
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <fc/stacktrace.hpp>
|
||||||
|
#include <fc/thread/thread.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(fc_stacktrace)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(stacktrace_test)
|
||||||
|
{
|
||||||
|
// print the stack trace
|
||||||
|
std::stringstream ss;
|
||||||
|
fc::print_stacktrace(ss);
|
||||||
|
std::string results = ss.str();
|
||||||
|
#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65
|
||||||
|
BOOST_CHECK(!results.empty());
|
||||||
|
BOOST_CHECK(results.find("fc::print_stacktrace") != std::string::npos);
|
||||||
|
#else
|
||||||
|
BOOST_CHECK(results.empty());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(threaded_stacktrace_test)
|
||||||
|
{
|
||||||
|
fc::thread test_thread("a_thread");
|
||||||
|
std::string results = test_thread.async(
|
||||||
|
[] ()->std::string {
|
||||||
|
// cause a pause
|
||||||
|
for(int i = 0; i < 10000; i++);
|
||||||
|
std::stringstream ss;
|
||||||
|
fc::print_stacktrace(ss);
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
).wait();
|
||||||
|
#if BOOST_VERSION / 100000 >= 1 && ((BOOST_VERSION / 100) % 1000) >= 65
|
||||||
|
BOOST_CHECK(!results.empty());
|
||||||
|
BOOST_CHECK(results.find("fc::print_stacktrace") != std::string::npos);
|
||||||
|
#else
|
||||||
|
BOOST_CHECK(results.empty());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this test causes a segfault on purpose to test the event handler
|
||||||
|
BOOST_AUTO_TEST_CASE(cause_segfault)
|
||||||
|
{
|
||||||
|
fc::print_stacktrace_on_segfault();
|
||||||
|
::raise(SIGSEGV);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
@ -37,8 +37,9 @@ BOOST_AUTO_TEST_CASE(time_point_sec_test)
|
||||||
BOOST_CHECK_EQUAL( "20380119T031408", tp2g.to_non_delimited_iso_string() );
|
BOOST_CHECK_EQUAL( "20380119T031408", tp2g.to_non_delimited_iso_string() );
|
||||||
|
|
||||||
time_point_sec tp3g(0xc0000000U);
|
time_point_sec tp3g(0xc0000000U);
|
||||||
BOOST_CHECK_EQUAL( "2072-01-28T16:51:12", tp3g.to_iso_string() );
|
// commented next 2 tests as they will only work with boost >= 1.64
|
||||||
BOOST_CHECK_EQUAL( "20720128T165112", tp3g.to_non_delimited_iso_string() );
|
//BOOST_CHECK_EQUAL( "2072-01-28T16:51:12", tp3g.to_iso_string() );
|
||||||
|
//BOOST_CHECK_EQUAL( "20720128T165112", tp3g.to_non_delimited_iso_string() );
|
||||||
|
|
||||||
BOOST_CHECK( tp0 == time_point_sec() );
|
BOOST_CHECK( tp0 == time_point_sec() );
|
||||||
BOOST_CHECK( tp0 < tp1 );
|
BOOST_CHECK( tp0 < tp1 );
|
||||||
|
|
|
||||||
184
tests/variant_test.cpp
Normal file
184
tests/variant_test.cpp
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <fc/log/logger.hpp>
|
||||||
|
|
||||||
|
#include <fc/container/flat.hpp>
|
||||||
|
#include <fc/io/raw.hpp>
|
||||||
|
#include <fc/reflect/variant.hpp>
|
||||||
|
#include <fc/static_variant.hpp>
|
||||||
|
#include <fc/log/logger_config.hpp>
|
||||||
|
|
||||||
|
namespace fc { namespace test {
|
||||||
|
|
||||||
|
struct item;
|
||||||
|
inline bool operator == ( const item& a, const item& b );
|
||||||
|
inline bool operator < ( const item& a, const item& b );
|
||||||
|
|
||||||
|
struct item_wrapper
|
||||||
|
{
|
||||||
|
item_wrapper() {}
|
||||||
|
item_wrapper(item&& it) { v.reserve(1); v.insert( it ); }
|
||||||
|
boost::container::flat_set<struct item> v;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator == ( const item_wrapper& a, const item_wrapper& b )
|
||||||
|
{ return ( std::tie( a.v ) == std::tie( b.v ) ); }
|
||||||
|
inline bool operator < ( const item_wrapper& a, const item_wrapper& b )
|
||||||
|
{ return ( std::tie( a.v ) < std::tie( b.v ) ); }
|
||||||
|
|
||||||
|
struct item
|
||||||
|
{
|
||||||
|
item(int32_t lvl = 0) : level(lvl) {}
|
||||||
|
item(item_wrapper&& wp, int32_t lvl = 0) : level(lvl), w(wp) {}
|
||||||
|
int32_t level;
|
||||||
|
item_wrapper w;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool operator == ( const item& a, const item& b )
|
||||||
|
{ return ( std::tie( a.level, a.w ) == std::tie( b.level, b.w ) ); }
|
||||||
|
inline bool operator < ( const item& a, const item& b )
|
||||||
|
{ return ( std::tie( a.level, a.w ) < std::tie( b.level, b.w ) ); }
|
||||||
|
|
||||||
|
|
||||||
|
} } // namespace fc::test
|
||||||
|
|
||||||
|
FC_REFLECT( fc::test::item_wrapper, (v) );
|
||||||
|
FC_REFLECT( fc::test::item, (level)(w) );
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(fc_variant_and_log)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( nested_objects_test )
|
||||||
|
{ try {
|
||||||
|
|
||||||
|
ilog( "Suppressing logging (but not disabled)" );
|
||||||
|
fc::logging_config cfg;
|
||||||
|
fc::logger_config dlc;
|
||||||
|
dlc.name = "default";
|
||||||
|
dlc.level = fc::log_level::debug;
|
||||||
|
dlc.appenders.push_back("stderr");
|
||||||
|
cfg.loggers.push_back( dlc );
|
||||||
|
fc::configure_logging( cfg );
|
||||||
|
|
||||||
|
auto create_nested_object = []( uint32_t level )
|
||||||
|
{
|
||||||
|
ilog( "Creating nested object with ${lv} level(s)", ("lv",level) );
|
||||||
|
fc::test::item nested;
|
||||||
|
for( uint32_t i = 1; i <= level; i++ )
|
||||||
|
{
|
||||||
|
if( i % 10 == 0 )
|
||||||
|
ilog( "Creating level ${lv}", ("lv",i) );
|
||||||
|
fc::test::item_wrapper wp( std::move(nested) );
|
||||||
|
nested = fc::test::item( std::move(wp), i );
|
||||||
|
}
|
||||||
|
return nested;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int nested_loops = 0; nested_loops <= 100; ++nested_loops )
|
||||||
|
{
|
||||||
|
int nested_levels = nested_loops * 3 + 2;
|
||||||
|
auto nested = create_nested_object( nested_loops );
|
||||||
|
|
||||||
|
fc::variant v;
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to nested object convert to variant. ==========" );
|
||||||
|
BOOST_CHECK_THROW( to_variant( nested, v, nested_levels ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
to_variant( nested, v, nested_levels ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (nested) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (nested) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (nested) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
to_variant( nested, v, nested_levels + 1 );
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to convert nested object from variant. ==========" );
|
||||||
|
fc::test::item unpacked;
|
||||||
|
BOOST_CHECK_THROW( from_variant( v, unpacked, nested_levels ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
from_variant( v, unpacked, nested_levels ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (v) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
from_variant( v, unpacked, nested_levels + 1 );
|
||||||
|
|
||||||
|
BOOST_CHECK( unpacked == nested );
|
||||||
|
|
||||||
|
// both log and dump should never throw
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to log obj. ==========" );
|
||||||
|
ilog( "The obj is ${a}, variant is ${v}", ("a",nested)("v",v) );
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to dump obj. ==========" );
|
||||||
|
idump( (nested)(v) );
|
||||||
|
|
||||||
|
fc::static_variant<fc::test::item> sv( nested ), sv1;
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to convert static_variant to variant. ==========" );
|
||||||
|
BOOST_CHECK_THROW( to_variant( sv, v, nested_levels + 1 ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
to_variant( sv, v, nested_levels + 1 ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (sv) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (sv) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (sv) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
to_variant( sv, v, nested_levels + 2 );
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to convert static_variant from variant. ==========" );
|
||||||
|
BOOST_CHECK_THROW( from_variant( v, sv1, nested_levels + 1 ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
from_variant( v, sv1, nested_levels + 1 ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (v) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
from_variant( v, sv1, nested_levels + 2 );
|
||||||
|
|
||||||
|
BOOST_CHECK( sv == sv1 );
|
||||||
|
|
||||||
|
// both log and dump should never throw
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to log static_variant. ==========" );
|
||||||
|
wlog( "The static_variant is ${a}, variant is $(v)", ("a",sv)("v",v) );
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to dump static_variant. ==========" );
|
||||||
|
wdump( (sv)(v) );
|
||||||
|
|
||||||
|
std::vector<fc::static_variant<fc::test::item>> vec(300), vec1;
|
||||||
|
for( int i = 0; i < 300; i++ )
|
||||||
|
vec.push_back(sv);
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to convert vector to variant. ==========" );
|
||||||
|
BOOST_CHECK_THROW( to_variant( vec, v, nested_levels + 2 ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
to_variant( vec, v, nested_levels + 2 ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (vec) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (vec) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (vec) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
to_variant( vec, v, nested_levels + 3 );
|
||||||
|
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to convert vector from variant. ==========" );
|
||||||
|
BOOST_CHECK_THROW( from_variant( v, vec1, nested_levels + 2 ), fc::assert_exception );
|
||||||
|
try{ try { try { try {
|
||||||
|
from_variant( v, vec1, nested_levels + 2 ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_LOG_AND_RETHROW( ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_RETHROW( (v) ); BOOST_FAIL( "Expected exception." );
|
||||||
|
} FC_CAPTURE_AND_LOG ( (v) ); // CAPTURE_AND_LOG should never throw again
|
||||||
|
|
||||||
|
from_variant( v, vec1, nested_levels + 3 );
|
||||||
|
|
||||||
|
BOOST_CHECK( vec == vec1 );
|
||||||
|
|
||||||
|
// both log and dump should never throw
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to log vector. ==========" );
|
||||||
|
elog( "The vector is ${a}, variant is ${v}", ("a",vec)("v",v) );
|
||||||
|
BOOST_TEST_MESSAGE( "========== About to dump vector. ==========" );
|
||||||
|
edump( (vec)(v) );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fc::configure_logging( fc::logging_config::default_config() );
|
||||||
|
ilog( "End suppressing logging" );
|
||||||
|
|
||||||
|
} FC_CAPTURE_LOG_AND_RETHROW ( (0) ) }
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
25
vendor/boost_1.51/include/boost/process.hpp
vendored
25
vendor/boost_1.51/include/boost/process.hpp
vendored
|
|
@ -1,25 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process.hpp
|
|
||||||
*
|
|
||||||
* Convenience header that includes all public Boost.Process header files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_HPP
|
|
||||||
#define BOOST_PROCESS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/all.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
40
vendor/boost_1.51/include/boost/process/all.hpp
vendored
40
vendor/boost_1.51/include/boost/process/all.hpp
vendored
|
|
@ -1,40 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/all.hpp
|
|
||||||
*
|
|
||||||
* Convenience header that includes all public Boost.Process header files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_ALL_HPP
|
|
||||||
#define BOOST_PROCESS_ALL_HPP
|
|
||||||
|
|
||||||
#include <boost/process/child.hpp>
|
|
||||||
#include <boost/process/context.hpp>
|
|
||||||
#include <boost/process/environment.hpp>
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <boost/process/operations.hpp>
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
#include <boost/process/pipe.hpp>
|
|
||||||
#include <boost/process/pistream.hpp>
|
|
||||||
#include <boost/process/postream.hpp>
|
|
||||||
#include <boost/process/process.hpp>
|
|
||||||
#include <boost/process/self.hpp>
|
|
||||||
#include <boost/process/status.hpp>
|
|
||||||
#include <boost/process/stream_behavior.hpp>
|
|
||||||
#include <boost/process/stream_ends.hpp>
|
|
||||||
#include <boost/process/stream_id.hpp>
|
|
||||||
#include <boost/process/stream_type.hpp>
|
|
||||||
|
|
||||||
#endif
|
|
||||||
100
vendor/boost_1.51/include/boost/process/child.hpp
vendored
100
vendor/boost_1.51/include/boost/process/child.hpp
vendored
|
|
@ -1,100 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/child.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the child class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_CHILD_HPP
|
|
||||||
#define BOOST_PROCESS_CHILD_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/process.hpp>
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
#include <boost/process/stream_id.hpp>
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The child class provides access to a child process.
|
|
||||||
*/
|
|
||||||
class child : public process
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a new child object that represents the just spawned child
|
|
||||||
* process \a id.
|
|
||||||
*/
|
|
||||||
child(pid_type id, std::map<stream_id, handle> handles)
|
|
||||||
: process(id),
|
|
||||||
handles_(handles)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
/**
|
|
||||||
* Creates a new child object that represents the just spawned child
|
|
||||||
* process \a id.
|
|
||||||
*
|
|
||||||
* This operation is only available on Windows systems.
|
|
||||||
*/
|
|
||||||
child(handle hprocess, std::map<stream_id, handle> handles)
|
|
||||||
: process(hprocess),
|
|
||||||
handles_(handles)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a handle to a stream attached to the child.
|
|
||||||
*
|
|
||||||
* If the handle doesn't exist an invalid handle is returned.
|
|
||||||
*/
|
|
||||||
handle get_handle(stream_id id) const
|
|
||||||
{
|
|
||||||
std::map<stream_id, handle>::const_iterator it = handles_.find(id);
|
|
||||||
return (it != handles_.end()) ? it->second : handle();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
handle::native_type get_os_handle() const
|
|
||||||
{
|
|
||||||
return handle_.native();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Handles providing access to streams attached to the child process.
|
|
||||||
*/
|
|
||||||
std::map<stream_id, handle> handles_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/config.hpp
|
|
||||||
*
|
|
||||||
* Defines macros that are used by the library to determine the operating
|
|
||||||
* system it is running under and the features it supports.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_CONFIG_HPP
|
|
||||||
#define BOOST_PROCESS_CONFIG_HPP
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/system/config.hpp>
|
|
||||||
#include <boost/system/system_error.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <errno.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
# if !defined(BOOST_PROCESS_POSIX_PATH_MAX) || defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Specifies the system's maximal supported path length.
|
|
||||||
*
|
|
||||||
* The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer
|
|
||||||
* value which specifies the system's maximal supported path length. It is
|
|
||||||
* only used if neither PATH_MAX nor _PC_PATH_MAX and HAVE_PATHCONF are defined.
|
|
||||||
* The maximal supported path length is required by
|
|
||||||
* boost::process::self::get_work_dir(). Please note that this function is
|
|
||||||
* also called by the constructor of boost::process::context.
|
|
||||||
*/
|
|
||||||
# define BOOST_PROCESS_POSIX_PATH_MAX 259
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \cond */
|
|
||||||
#define BOOST_PROCESS_SOURCE_LOCATION \
|
|
||||||
"in file '" __FILE__ "', line " BOOST_STRINGIZE(__LINE__) ": "
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# define BOOST_PROCESS_LAST_ERROR errno
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# define BOOST_PROCESS_LAST_ERROR GetLastError()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
|
|
||||||
boost::throw_exception(boost::system::system_error( \
|
|
||||||
boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
|
|
||||||
boost::system::get_system_category()), \
|
|
||||||
BOOST_PROCESS_SOURCE_LOCATION what))
|
|
||||||
|
|
||||||
#define BOOST_PROCESS_THROW_ERROR(error, what) \
|
|
||||||
boost::throw_exception(boost::system::system_error( \
|
|
||||||
boost::system::error_code(error, \
|
|
||||||
boost::system::get_system_category()), \
|
|
||||||
BOOST_PROCESS_SOURCE_LOCATION what))
|
|
||||||
/** \endcond */
|
|
||||||
|
|
||||||
#endif
|
|
||||||
139
vendor/boost_1.51/include/boost/process/context.hpp
vendored
139
vendor/boost_1.51/include/boost/process/context.hpp
vendored
|
|
@ -1,139 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/context.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the context class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_CONTEXT_HPP
|
|
||||||
#define BOOST_PROCESS_CONTEXT_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <unistd.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/stream_id.hpp>
|
|
||||||
#include <boost/process/stream_ends.hpp>
|
|
||||||
#include <boost/process/stream_type.hpp>
|
|
||||||
#include <boost/process/environment.hpp>
|
|
||||||
#include <boost/process/self.hpp>
|
|
||||||
#include <boost/process/stream_behavior.hpp>
|
|
||||||
#include <boost/function.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context class to define how a child process is created.
|
|
||||||
*
|
|
||||||
* The context class is used to configure streams, to set the work directory
|
|
||||||
* and define environment variables. It is also used to change a process
|
|
||||||
* name (the variable commonly known as argv[0]).
|
|
||||||
*/
|
|
||||||
struct context
|
|
||||||
{
|
|
||||||
typedef std::map<stream_id, boost::function<stream_ends (stream_type)> >
|
|
||||||
streams_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Streams.
|
|
||||||
*
|
|
||||||
* Streams of a child process can be configured through factory functions
|
|
||||||
* which return a pair of handles - one handle to use as a stream end
|
|
||||||
* in the child process and possibly another handle to use as a stream end
|
|
||||||
* in the parent process (if a pipe is setup both processes can communicate
|
|
||||||
* with each other).
|
|
||||||
*/
|
|
||||||
streams_t streams;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process name.
|
|
||||||
*
|
|
||||||
* The child process can access the process name via a variable
|
|
||||||
* commonly known as argv[0].
|
|
||||||
*/
|
|
||||||
std::string process_name;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Work directory.
|
|
||||||
*/
|
|
||||||
std::string work_dir;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Environment variables.
|
|
||||||
*/
|
|
||||||
environment env;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suppress creation of a console window on win32 (nop on other platforms)
|
|
||||||
*/
|
|
||||||
bool suppress_console;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a process context.
|
|
||||||
*
|
|
||||||
* The default behavior of standard streams is to inherit them. The current
|
|
||||||
* work directory is also the work directory of the child process. The child
|
|
||||||
* process also inherits all environment variables.
|
|
||||||
*/
|
|
||||||
context()
|
|
||||||
: work_dir(self::get_work_dir()),
|
|
||||||
env(self::get_environment()),
|
|
||||||
suppress_console(false)
|
|
||||||
{
|
|
||||||
#if 0 // this default behavior will throw in non-console apps
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
streams[stdin_id] = behavior::inherit(STDIN_FILENO);
|
|
||||||
streams[stdout_id] = behavior::inherit(STDOUT_FILENO);
|
|
||||||
streams[stderr_id] = behavior::inherit(STDERR_FILENO);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
streams[stdin_id] = behavior::inherit(GetStdHandle(STD_INPUT_HANDLE));
|
|
||||||
streams[stdout_id] = behavior::inherit(GetStdHandle(STD_OUTPUT_HANDLE));
|
|
||||||
streams[stderr_id] = behavior::inherit(GetStdHandle(STD_ERROR_HANDLE));
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Setups a child process.
|
|
||||||
*
|
|
||||||
* This is an extension point to support more configuration options for
|
|
||||||
* child processes. You can initialize \a setup with a user-defined function
|
|
||||||
* which is called when a child process is created.
|
|
||||||
*
|
|
||||||
* On POSIX platforms setup() is called in the child process. That's why in
|
|
||||||
* a multithreaded application only async-signal-safe functions must be
|
|
||||||
* called in the function \a setup is bound to.
|
|
||||||
*
|
|
||||||
* On Windows platforms setup() is called in the parent process. A
|
|
||||||
* reference to a STARTUPINFOA structure is passed as parameter.
|
|
||||||
*/
|
|
||||||
boost::function<void ()> setup;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
boost::function<void (STARTUPINFOA&)> setup;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/basic_status.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the basic status class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
|
|
||||||
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The basic_status class to wait for processes to exit.
|
|
||||||
*
|
|
||||||
* The basic_status class is a Boost.Asio I/O object and supports synchronous
|
|
||||||
* and asynchronous wait operations. It must be instantiated with a Service.
|
|
||||||
*/
|
|
||||||
template <typename Service>
|
|
||||||
class basic_status
|
|
||||||
: public boost::asio::basic_io_object<Service>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit basic_status(boost::asio::io_service &io_service)
|
|
||||||
: boost::asio::basic_io_object<Service>(io_service)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits synchronously for a process to exit.
|
|
||||||
*/
|
|
||||||
int wait(pid_type pid)
|
|
||||||
{
|
|
||||||
return this->service.wait(this->implementation, pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Waits asynchronously for a process to exit.
|
|
||||||
*/
|
|
||||||
template <typename Handler>
|
|
||||||
void async_wait(pid_type pid, Handler handler)
|
|
||||||
{
|
|
||||||
this->service.async_wait(this->implementation, pid, handler);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,323 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/basic_status_service.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the basic status service class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
|
|
||||||
#define BOOST_PROCESS_DETAIL_BASIC_STATUS_SERVICE_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <boost/process/operations.hpp>
|
|
||||||
# include <string>
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/wait.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
#include <boost/process/detail/status_impl.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
#include <boost/scoped_ptr.hpp>
|
|
||||||
#include <boost/system/error_code.hpp>
|
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <vector>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The basic_status_service class provides the service to wait for processes
|
|
||||||
* synchronously and asynchronously.
|
|
||||||
*/
|
|
||||||
template <typename StatusImplementation = status_impl>
|
|
||||||
class basic_status_service
|
|
||||||
: public boost::asio::detail::service_base<StatusImplementation>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit basic_status_service(boost::asio::io_service &io_service)
|
|
||||||
: boost::asio::detail::service_base<StatusImplementation>(io_service),
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
interrupt_pid_(-1),
|
|
||||||
pids_(0)
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
run_(true)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
handles_.push_back(CreateEvent(NULL, FALSE, FALSE, NULL));
|
|
||||||
if (handles_[0] == NULL)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed");
|
|
||||||
work_thread_ = boost::thread(
|
|
||||||
&basic_status_service<StatusImplementation>::work_thread, this);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
~basic_status_service()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
bool worker_thread_active = (pids_ != 0);
|
|
||||||
lock.unlock();
|
|
||||||
if (worker_thread_active)
|
|
||||||
{
|
|
||||||
stop_work_thread();
|
|
||||||
work_thread_.join();
|
|
||||||
}
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
stop_work_thread();
|
|
||||||
work_thread_.join();
|
|
||||||
CloseHandle(handles_[0]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<StatusImplementation> implementation_type;
|
|
||||||
|
|
||||||
void construct(implementation_type &impl)
|
|
||||||
{
|
|
||||||
impl = boost::make_shared<StatusImplementation>();
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
impls_.push_back(impl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy(implementation_type &impl)
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
typename std::vector<implementation_type>::iterator it =
|
|
||||||
std::find(impls_.begin(), impls_.end(), impl);
|
|
||||||
if (it != impls_.end())
|
|
||||||
impls_.erase(it);
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
interrupt_work_thread();
|
|
||||||
work_thread_cond_.wait(work_thread_mutex_);
|
|
||||||
impl->clear(handles_);
|
|
||||||
work_thread_cond_.notify_all();
|
|
||||||
#endif
|
|
||||||
impl.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
int wait(implementation_type &impl, pid_type pid)
|
|
||||||
{
|
|
||||||
boost::system::error_code ec;
|
|
||||||
int status = impl->wait(pid, ec);
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (ec.value() == ECHILD)
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
boost::unordered_map<pid_t, int>::iterator it = statuses_.find(pid);
|
|
||||||
if (it == statuses_.end())
|
|
||||||
{
|
|
||||||
work_thread_cond_.wait(work_thread_mutex_);
|
|
||||||
it = statuses_.find(pid);
|
|
||||||
}
|
|
||||||
if (it != statuses_.end())
|
|
||||||
{
|
|
||||||
status = it->second;
|
|
||||||
statuses_.erase(it);
|
|
||||||
ec.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
boost::asio::detail::throw_error(ec);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
void async_wait(implementation_type &impl, pid_type pid, Handler handler)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
if (++pids_ == 1)
|
|
||||||
{
|
|
||||||
// if there was a previous worker thread that exited because
|
|
||||||
// pids_ dropped to 0, we must join it now to free the thread's
|
|
||||||
// memory before launching a new worker thread
|
|
||||||
if (work_thread_.joinable())
|
|
||||||
work_thread_.join();
|
|
||||||
work_.reset(new boost::asio::io_service::work(
|
|
||||||
this->get_io_service()));
|
|
||||||
work_thread_ = boost::thread(
|
|
||||||
&basic_status_service<StatusImplementation>::work_thread,
|
|
||||||
this);
|
|
||||||
}
|
|
||||||
impl->async_wait(pid, this->get_io_service().wrap(handler));
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
|
|
||||||
FALSE, pid);
|
|
||||||
if (handle == NULL)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
if (!work_)
|
|
||||||
work_.reset(new boost::asio::io_service::work(
|
|
||||||
this->get_io_service()));
|
|
||||||
interrupt_work_thread();
|
|
||||||
work_thread_cond_.wait(work_thread_mutex_);
|
|
||||||
handles_.push_back(handle);
|
|
||||||
impl->async_wait(handle, this->get_io_service().wrap(handler));
|
|
||||||
work_thread_cond_.notify_all();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void shutdown_service()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
work_.reset();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void work_thread()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
pid_t pid = ::wait(&status);
|
|
||||||
if (pid == -1)
|
|
||||||
{
|
|
||||||
if (errno != EINTR)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("wait(2) failed");
|
|
||||||
}
|
|
||||||
else if (interrupted(pid))
|
|
||||||
{
|
|
||||||
// On POSIX the only reason to interrupt is to break out.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
bool regchild = false;
|
|
||||||
for (typename std::vector<implementation_type>::iterator it =
|
|
||||||
impls_.begin(); it != impls_.end(); ++it)
|
|
||||||
regchild |= (*it)->complete(pid, status);
|
|
||||||
if (regchild && --pids_ == 0)
|
|
||||||
{
|
|
||||||
work_.reset();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (!regchild)
|
|
||||||
{
|
|
||||||
statuses_.insert(boost::unordered_map<pid_t, int>::
|
|
||||||
value_type(pid, status));
|
|
||||||
work_thread_cond_.notify_all();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
DWORD res = WaitForMultipleObjects(handles_.size(), &handles_[0],
|
|
||||||
FALSE, INFINITE);
|
|
||||||
if (res == WAIT_FAILED)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"WaitForMultipleObjects() failed");
|
|
||||||
else if (res - WAIT_OBJECT_0 == 0)
|
|
||||||
{
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
if (!run_)
|
|
||||||
break;
|
|
||||||
work_thread_cond_.notify_all();
|
|
||||||
work_thread_cond_.wait(work_thread_mutex_);
|
|
||||||
}
|
|
||||||
else if (res - WAIT_OBJECT_0 > 0)
|
|
||||||
{
|
|
||||||
HANDLE handle = handles_[res - WAIT_OBJECT_0];
|
|
||||||
DWORD exit_code;
|
|
||||||
if (!GetExitCodeProcess(handle, &exit_code))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"GetExitCodeProcess() failed");
|
|
||||||
boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
|
|
||||||
for (typename std::vector<implementation_type>::iterator it =
|
|
||||||
impls_.begin(); it != impls_.end(); ++it)
|
|
||||||
(*it)->complete(handle, exit_code);
|
|
||||||
std::vector<HANDLE>::iterator it = handles_.begin();
|
|
||||||
std::advance(it, res - WAIT_OBJECT_0);
|
|
||||||
handles_.erase(it);
|
|
||||||
if (handles_.size() == 1)
|
|
||||||
work_.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void interrupt_work_thread()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
// By creating a child process which immediately exits
|
|
||||||
// we interrupt wait().
|
|
||||||
std::vector<std::string> args;
|
|
||||||
args.push_back("-c");
|
|
||||||
args.push_back("'exit'");
|
|
||||||
interrupt_pid_ = create_child("/bin/sh", args).get_id();
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
// By signaling the event in the first slot WaitForMultipleObjects()
|
|
||||||
// will return. The work thread won't do anything except checking if
|
|
||||||
// it should continue to run.
|
|
||||||
if (!SetEvent(handles_[0]))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetEvent() failed");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
bool interrupted(pid_t pid)
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(work_thread_mutex_);
|
|
||||||
return interrupt_pid_ == pid;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void stop_work_thread()
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock(work_thread_mutex_);
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
// Access to run_ must be sychronized with running().
|
|
||||||
run_ = false;
|
|
||||||
#endif
|
|
||||||
// Access to interrupt_pid_ must be sychronized with interrupted().
|
|
||||||
interrupt_work_thread();
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::scoped_ptr<boost::asio::io_service::work> work_;
|
|
||||||
std::vector<implementation_type> impls_;
|
|
||||||
boost::mutex work_thread_mutex_;
|
|
||||||
boost::thread work_thread_;
|
|
||||||
boost::condition_variable_any work_thread_cond_;
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
pid_t interrupt_pid_;
|
|
||||||
int pids_;
|
|
||||||
boost::unordered_map<pid_t, int> statuses_;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
bool run_;
|
|
||||||
std::vector<HANDLE> handles_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,106 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/posix_helpers.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of helper functions for POSIX systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP
|
|
||||||
#define BOOST_PROCESS_POSIX_HELPERS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/process/environment.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <utility>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an environment to a char** table as used by execve().
|
|
||||||
*
|
|
||||||
* Converts the environment's contents to the format used by the
|
|
||||||
* execve() system call. The returned char** array is allocated
|
|
||||||
* in dynamic memory; the caller must free it when not used any
|
|
||||||
* more. Each entry is also allocated in dynamic memory and is a
|
|
||||||
* NULL-terminated string of the form var=value; these must also be
|
|
||||||
* released by the caller.
|
|
||||||
*
|
|
||||||
* This operation is only available on POSIX systems.
|
|
||||||
*
|
|
||||||
* \return The first argument of the pair is an integer that indicates
|
|
||||||
* how many strings are stored in the second argument. The
|
|
||||||
* second argument is a NULL-terminated, dynamically allocated
|
|
||||||
* array of dynamically allocated strings representing the
|
|
||||||
* enviroment's content. Each array entry is a NULL-terminated
|
|
||||||
* string of the form var=value. The caller is responsible for
|
|
||||||
* freeing them.
|
|
||||||
*/
|
|
||||||
inline std::pair<std::size_t, char**> environment_to_envp(const environment
|
|
||||||
&env)
|
|
||||||
{
|
|
||||||
std::size_t nargs = env.size();
|
|
||||||
char **envp = new char*[nargs + 1];
|
|
||||||
environment::size_type i = 0;
|
|
||||||
for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
|
|
||||||
{
|
|
||||||
std::string s = it->first + "=" + it->second;
|
|
||||||
envp[i] = new char[s.size() + 1];
|
|
||||||
std::strncpy(envp[i], s.c_str(), s.size() + 1);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
envp[i] = 0;
|
|
||||||
return std::pair<std::size_t, char**>(nargs, envp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the command line to an array of C strings.
|
|
||||||
*
|
|
||||||
* Converts the command line's list of arguments to the format expected
|
|
||||||
* by the \a argv parameter in the POSIX execve() system call.
|
|
||||||
*
|
|
||||||
* This operation is only available on POSIX systems.
|
|
||||||
*
|
|
||||||
* \return The first argument of the pair is an integer that indicates
|
|
||||||
* how many strings are stored in the second argument. The
|
|
||||||
* second argument is a NULL-terminated, dynamically allocated
|
|
||||||
* array of dynamically allocated strings holding the arguments
|
|
||||||
* to the executable. The caller is responsible for freeing them.
|
|
||||||
*/
|
|
||||||
template <class Arguments>
|
|
||||||
inline std::pair<std::size_t, char**> collection_to_argv(const Arguments &args)
|
|
||||||
{
|
|
||||||
std::size_t nargs = args.size();
|
|
||||||
char **argv = new char*[nargs + 1];
|
|
||||||
typename Arguments::size_type i = 0;
|
|
||||||
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
argv[i] = new char[it->size() + 1];
|
|
||||||
std::strncpy(argv[i], it->c_str(), it->size() + 1);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
argv[nargs] = 0;
|
|
||||||
return std::pair<std::size_t, char**>(nargs, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,190 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/status_impl.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the status implementation class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
|
||||||
#define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <signal.h>
|
|
||||||
# include <sys/wait.h>
|
|
||||||
# include <errno.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
#include <boost/system/error_code.hpp>
|
|
||||||
#include <boost/ptr_container/ptr_unordered_map.hpp>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
typedef pid_t phandle;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef HANDLE phandle;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct operation
|
|
||||||
{
|
|
||||||
virtual ~operation(){}
|
|
||||||
virtual void operator()(int exit_code)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_MSVC)
|
|
||||||
exit_code;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
class wrapped_handler : public operation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
wrapped_handler(Handler handler)
|
|
||||||
: handler_(handler)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator()(int exit_code)
|
|
||||||
{
|
|
||||||
handler_(boost::system::error_code(), exit_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
Handler handler_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The status_impl class saves internal data of every status I/O object.
|
|
||||||
*/
|
|
||||||
class status_impl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
template <typename Container>
|
|
||||||
void clear(Container &handles)
|
|
||||||
{
|
|
||||||
for (operations_type::iterator it = ops_.begin(); it != ops_.end();
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
for (typename Container::iterator it2 = handles.begin(); it2 !=
|
|
||||||
handles.end(); ++it2)
|
|
||||||
{
|
|
||||||
if (*it2 == it->first)
|
|
||||||
{
|
|
||||||
handles.erase(it2);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(it->first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int wait(pid_type pid, boost::system::error_code &ec)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
pid_t p;
|
|
||||||
int status;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
p = waitpid(pid, &status, 0);
|
|
||||||
} while (p == -1 && errno == EINTR);
|
|
||||||
if (p == -1)
|
|
||||||
{
|
|
||||||
ec = boost::system::error_code(errno,
|
|
||||||
boost::system::get_system_category());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return status;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
|
|
||||||
pid);
|
|
||||||
if (h == NULL)
|
|
||||||
{
|
|
||||||
ec = boost::system::error_code(GetLastError(),
|
|
||||||
boost::system::get_system_category());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
|
|
||||||
{
|
|
||||||
CloseHandle(h);
|
|
||||||
ec = boost::system::error_code(GetLastError(),
|
|
||||||
boost::system::get_system_category());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD exit_code;
|
|
||||||
if (!GetExitCodeProcess(h, &exit_code))
|
|
||||||
{
|
|
||||||
CloseHandle(h);
|
|
||||||
ec = boost::system::error_code(GetLastError(),
|
|
||||||
boost::system::get_system_category());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!CloseHandle(h))
|
|
||||||
{
|
|
||||||
ec = boost::system::error_code(GetLastError(),
|
|
||||||
boost::system::get_system_category());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return exit_code;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Handler>
|
|
||||||
void async_wait(phandle ph, Handler handler)
|
|
||||||
{
|
|
||||||
ops_.insert(ph, new wrapped_handler<Handler>(handler));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool complete(phandle ph, int exit_code)
|
|
||||||
{
|
|
||||||
boost::iterator_range<operations_type::iterator> r =
|
|
||||||
ops_.equal_range(ph);
|
|
||||||
if (r.empty())
|
|
||||||
return false;
|
|
||||||
for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
|
|
||||||
(*it->second)(exit_code);
|
|
||||||
ops_.erase(r.begin(), r.end());
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
if (!CloseHandle(ph))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
|
||||||
#endif
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
|
|
||||||
operations_type ops_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,228 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/systembuf.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the systembuf class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
|
|
||||||
#define BOOST_PROCESS_DETAIL_SYSTEMBUF_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/scoped_array.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <streambuf>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
class postream;
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* std::streambuf implementation for handles.
|
|
||||||
*
|
|
||||||
* systembuf provides a std::streambuf implementation for handles.
|
|
||||||
* Contrarywise to the handle class, this class does \b not take
|
|
||||||
* ownership of the native handle; this should be taken care of
|
|
||||||
* somewhere else.
|
|
||||||
*
|
|
||||||
* This class follows the expected semantics of a std::streambuf object.
|
|
||||||
* However, it is not copyable to avoid introducing inconsistences with
|
|
||||||
* the on-disk file and the in-memory buffers.
|
|
||||||
*/
|
|
||||||
class systembuf : public std::streambuf, public boost::noncopyable
|
|
||||||
{
|
|
||||||
friend class boost::process::postream;
|
|
||||||
|
|
||||||
public:
|
|
||||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Opaque name for the native handle type.
|
|
||||||
*/
|
|
||||||
typedef NativeHandleType handle_type;
|
|
||||||
#elif defined(BOOST_POSIX_API)
|
|
||||||
typedef int handle_type;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef HANDLE handle_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new systembuf for the given handle.
|
|
||||||
*
|
|
||||||
* This constructor creates a new systembuf object that reads or
|
|
||||||
* writes data from/to the \a h native handle. This handle
|
|
||||||
* is \b not owned by the created systembuf object; the code
|
|
||||||
* should take care of it externally.
|
|
||||||
*
|
|
||||||
* This class buffers input and output; the buffer size may be
|
|
||||||
* tuned through the \a bufsize parameter, which defaults to 8192
|
|
||||||
* bytes.
|
|
||||||
*
|
|
||||||
* \see pistream and postream
|
|
||||||
*/
|
|
||||||
explicit systembuf(handle_type h, std::size_t bufsize = 8192)
|
|
||||||
: handle_(h),
|
|
||||||
bufsize_(bufsize),
|
|
||||||
read_buf_(new char[bufsize]),
|
|
||||||
write_buf_(new char[bufsize])
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
BOOST_ASSERT(handle_ >= 0);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
BOOST_ASSERT(handle_ != INVALID_HANDLE_VALUE);
|
|
||||||
#endif
|
|
||||||
BOOST_ASSERT(bufsize_ > 0);
|
|
||||||
setp(write_buf_.get(), write_buf_.get() + bufsize_);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* Reads new data from the native handle.
|
|
||||||
*
|
|
||||||
* This operation is called by input methods when there is no more
|
|
||||||
* data in the input buffer. The function fills the buffer with new
|
|
||||||
* data, if available.
|
|
||||||
*
|
|
||||||
* \pre All input positions are exhausted (gptr() >= egptr()).
|
|
||||||
* \post The input buffer has new data, if available.
|
|
||||||
* \returns traits_type::eof() if a read error occurrs or there are
|
|
||||||
* no more data to be read. Otherwise returns
|
|
||||||
* traits_type::to_int_type(*gptr()).
|
|
||||||
*/
|
|
||||||
virtual int_type underflow()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(gptr() >= egptr());
|
|
||||||
|
|
||||||
bool ok;
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
ssize_t cnt = read(handle_, read_buf_.get(), bufsize_);
|
|
||||||
ok = (cnt != -1 && cnt != 0);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
DWORD cnt;
|
|
||||||
BOOL res = ReadFile(handle_, read_buf_.get(), bufsize_, &cnt, NULL);
|
|
||||||
ok = (res && cnt > 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!ok)
|
|
||||||
return traits_type::eof();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setg(read_buf_.get(), read_buf_.get(), read_buf_.get() + cnt);
|
|
||||||
return traits_type::to_int_type(*gptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Makes room in the write buffer for additional data.
|
|
||||||
*
|
|
||||||
* This operation is called by output methods when there is no more
|
|
||||||
* space in the output buffer to hold a new element. The function
|
|
||||||
* first flushes the buffer's contents to disk and then clears it to
|
|
||||||
* leave room for more characters. The given \a c character is
|
|
||||||
* stored at the beginning of the new space.
|
|
||||||
*
|
|
||||||
* \pre All output positions are exhausted (pptr() >= epptr()).
|
|
||||||
* \post The output buffer has more space if no errors occurred
|
|
||||||
* during the write to disk.
|
|
||||||
* \post *(pptr() - 1) is \a c.
|
|
||||||
* \returns traits_type::eof() if a write error occurrs. Otherwise
|
|
||||||
* returns traits_type::not_eof(c).
|
|
||||||
*/
|
|
||||||
virtual int_type overflow(int c)
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(pptr() >= epptr());
|
|
||||||
|
|
||||||
if (sync() == -1)
|
|
||||||
return traits_type::eof();
|
|
||||||
|
|
||||||
if (!traits_type::eq_int_type(c, traits_type::eof()))
|
|
||||||
{
|
|
||||||
traits_type::assign(*pptr(), static_cast<traits_type::char_type>(
|
|
||||||
c));
|
|
||||||
pbump(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return traits_type::not_eof(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes the output buffer to disk.
|
|
||||||
*
|
|
||||||
* Synchronizes the systembuf buffers with the contents of the file
|
|
||||||
* associated to this object through the native handle. The output buffer
|
|
||||||
* is flushed to disk and cleared to leave new room for more data.
|
|
||||||
*
|
|
||||||
* \returns 0 on success, -1 if an error occurred.
|
|
||||||
*/
|
|
||||||
virtual int sync()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
ssize_t cnt = pptr() - pbase();
|
|
||||||
bool ok = (write(handle_, pbase(), cnt) == cnt);
|
|
||||||
if (ok)
|
|
||||||
pbump(-cnt);
|
|
||||||
return ok ? 0 : -1;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
long cnt = pptr() - pbase();
|
|
||||||
DWORD rcnt;
|
|
||||||
BOOL res = WriteFile(handle_, pbase(), cnt, &rcnt, NULL);
|
|
||||||
bool ok = (res && static_cast<long>(rcnt) == cnt);
|
|
||||||
if (ok)
|
|
||||||
pbump(-cnt);
|
|
||||||
return ok ? 0 : -1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Native handle used by the systembuf object.
|
|
||||||
*/
|
|
||||||
handle_type handle_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal buffer size used during read and write operations.
|
|
||||||
*/
|
|
||||||
std::size_t bufsize_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal buffer used during read operations.
|
|
||||||
*/
|
|
||||||
boost::scoped_array<char> read_buf_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal buffer used during write operations.
|
|
||||||
*/
|
|
||||||
boost::scoped_array<char> write_buf_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,138 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/detail/windows_helpers.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of helper functions for Windows systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_WINDOWS_HELPERS_HPP
|
|
||||||
#define BOOST_PROCESS_WINDOWS_HELPERS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/process/environment.hpp>
|
|
||||||
#include <boost/shared_array.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string.h>
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an environment to a string used by CreateProcess().
|
|
||||||
*
|
|
||||||
* Converts the environment's contents to the format used by the
|
|
||||||
* CreateProcess() system call. The returned char* string is
|
|
||||||
* allocated in dynamic memory; the caller must free it when not
|
|
||||||
* used any more. This is enforced by the use of a shared pointer.
|
|
||||||
*
|
|
||||||
* This operation is only available on Windows systems.
|
|
||||||
*
|
|
||||||
* \return A dynamically allocated char* string that represents
|
|
||||||
* the environment's content. This string is of the form
|
|
||||||
* var1=value1\\0var2=value2\\0\\0.
|
|
||||||
*/
|
|
||||||
inline boost::shared_array<char> environment_to_windows_strings(environment
|
|
||||||
&env)
|
|
||||||
{
|
|
||||||
boost::shared_array<char> envp;
|
|
||||||
|
|
||||||
if (env.empty())
|
|
||||||
{
|
|
||||||
envp.reset(new char[2]);
|
|
||||||
ZeroMemory(envp.get(), 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string s;
|
|
||||||
for (environment::const_iterator it = env.begin(); it != env.end();
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
s += it->first + "=" + it->second;
|
|
||||||
s.push_back(0);
|
|
||||||
}
|
|
||||||
envp.reset(new char[s.size() + 1]);
|
|
||||||
#if (BOOST_MSVC >= 1400)
|
|
||||||
memcpy_s(envp.get(), s.size() + 1, s.c_str(), s.size() + 1);
|
|
||||||
#else
|
|
||||||
memcpy(envp.get(), s.c_str(), s.size() + 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
return envp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the command line to a plain string.
|
|
||||||
*
|
|
||||||
* Converts the command line's list of arguments to the format expected by the
|
|
||||||
* \a lpCommandLine parameter in the CreateProcess() system call.
|
|
||||||
*
|
|
||||||
* This operation is only available on Windows systems.
|
|
||||||
*
|
|
||||||
* \return A dynamically allocated string holding the command line
|
|
||||||
* to be passed to the executable. It is returned in a
|
|
||||||
* shared_array object to ensure its release at some point.
|
|
||||||
*/
|
|
||||||
template <class Arguments>
|
|
||||||
inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments
|
|
||||||
&args)
|
|
||||||
{
|
|
||||||
typedef std::vector<std::string> arguments_t;
|
|
||||||
arguments_t args2;
|
|
||||||
typename Arguments::size_type i = 0;
|
|
||||||
std::size_t size = 0;
|
|
||||||
for (typename Arguments::const_iterator it = args.begin(); it != args.end();
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
std::string arg = *it;
|
|
||||||
|
|
||||||
std::string::size_type pos = 0;
|
|
||||||
while ( (pos = arg.find('"', pos)) != std::string::npos)
|
|
||||||
{
|
|
||||||
arg.replace(pos, 1, "\\\"");
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arg.find(' ') != std::string::npos)
|
|
||||||
arg = '\"' + arg + '\"';
|
|
||||||
|
|
||||||
if (i++ != args.size() - 1)
|
|
||||||
arg += ' ';
|
|
||||||
|
|
||||||
args2.push_back(arg);
|
|
||||||
size += arg.size() + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::shared_array<char> cmdline(new char[size]);
|
|
||||||
cmdline.get()[0] = '\0';
|
|
||||||
for (arguments_t::size_type i = 0; i < args.size(); ++i)
|
|
||||||
#if (BOOST_MSVC >= 1400)
|
|
||||||
strcat_s(cmdline.get(), size, args2[i].c_str());
|
|
||||||
#else
|
|
||||||
strncat(cmdline.get(), args2[i].c_str(), args2[i].size());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return cmdline;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/environment.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the environment class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_ENVIRONMENT_HPP
|
|
||||||
#define BOOST_PROCESS_ENVIRONMENT_HPP
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Representation of a process' environment variables.
|
|
||||||
*
|
|
||||||
* The environment is a map that establishes an unidirectional
|
|
||||||
* association between variable names and their values and is
|
|
||||||
* represented by a string to string map.
|
|
||||||
*
|
|
||||||
* Variables may be defined to the empty string. Be aware that doing so
|
|
||||||
* is not portable: POSIX systems will treat such variables as being
|
|
||||||
* defined to the empty value, but Windows systems are not able to
|
|
||||||
* distinguish them from undefined variables.
|
|
||||||
*
|
|
||||||
* Neither POSIX nor Windows systems support a variable with no name.
|
|
||||||
*
|
|
||||||
* It is worthy to note that the environment is sorted alphabetically.
|
|
||||||
* This is provided for-free by the map container used to implement this
|
|
||||||
* type, and this behavior is required by Windows systems.
|
|
||||||
*/
|
|
||||||
typedef std::map<std::string, std::string> environment;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
231
vendor/boost_1.51/include/boost/process/handle.hpp
vendored
231
vendor/boost_1.51/include/boost/process/handle.hpp
vendored
|
|
@ -1,231 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/handle.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the handle class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_HANDLE_HPP
|
|
||||||
#define BOOST_PROCESS_HANDLE_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <unistd.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RAII model for handles.
|
|
||||||
*
|
|
||||||
* The \a handle class is a RAII model for native handles. This class wraps
|
|
||||||
* one of such handles grabbing its ownership, and automaticaly closes it
|
|
||||||
* upon destruction. It is used to avoid leaking open handles, shall an
|
|
||||||
* unexpected execution trace occur.
|
|
||||||
*/
|
|
||||||
class handle
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Opaque name for the native handle type.
|
|
||||||
*
|
|
||||||
* On POSIX systems \a NativeSystemHandle is an integer type while it is
|
|
||||||
* a \a HANDLE on Windows systems.
|
|
||||||
*/
|
|
||||||
typedef NativeSystemHandle native_type;
|
|
||||||
#elif defined(BOOST_POSIX_API)
|
|
||||||
typedef int native_type;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef HANDLE native_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs an invalid handle.
|
|
||||||
*
|
|
||||||
* \see valid()
|
|
||||||
*/
|
|
||||||
handle()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RAII settings to specify if handle should be automatically closed.
|
|
||||||
*/
|
|
||||||
enum close_type { do_close, dont_close };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a handle from a native handle.
|
|
||||||
*
|
|
||||||
* This constructor creates a new \a handle object that takes
|
|
||||||
* ownership of the given \a native handle. If \a close is set to
|
|
||||||
* handle::dont_close the \a native handle is not closed upon destruction.
|
|
||||||
* The user must not close \a native if it is owned by a \a handle object.
|
|
||||||
* Ownership can be reclaimed using release().
|
|
||||||
*
|
|
||||||
* \see release()
|
|
||||||
*/
|
|
||||||
handle(native_type native, close_type close = handle::do_close)
|
|
||||||
: impl_(boost::make_shared<impl>(native, close))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the handle is valid or not.
|
|
||||||
*
|
|
||||||
* \return true if the handle is valid; false otherwise.
|
|
||||||
*/
|
|
||||||
bool valid() const
|
|
||||||
{
|
|
||||||
return impl_ && impl_->valid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the handle.
|
|
||||||
*
|
|
||||||
* \post The handle is invalid.
|
|
||||||
* \post The native handle is closed.
|
|
||||||
*/
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
if (impl_)
|
|
||||||
impl_->close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the native handle.
|
|
||||||
*
|
|
||||||
* The caller can issue any operation on it except closing it.
|
|
||||||
* If closing is required, release() shall be used.
|
|
||||||
*
|
|
||||||
* \return The native handle.
|
|
||||||
*/
|
|
||||||
native_type native() const
|
|
||||||
{
|
|
||||||
return impl_ ? impl_->native() : invalid_handle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reclaims ownership of the native handle.
|
|
||||||
*
|
|
||||||
* The caller is responsible of closing the native handle.
|
|
||||||
*
|
|
||||||
* \post The handle is invalid.
|
|
||||||
* \return The native handle.
|
|
||||||
*/
|
|
||||||
native_type release()
|
|
||||||
{
|
|
||||||
return impl_ ? impl_->release() : invalid_handle();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
class impl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef handle::native_type native_type;
|
|
||||||
|
|
||||||
impl(native_type native, close_type close)
|
|
||||||
: native_(native),
|
|
||||||
close_(close)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~impl()
|
|
||||||
{
|
|
||||||
if (valid() && close_ == handle::do_close)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
::close(native_);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
CloseHandle(native_);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool valid() const
|
|
||||||
{
|
|
||||||
return native_ != handle::invalid_handle();
|
|
||||||
}
|
|
||||||
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
if (valid())
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
::close(native_);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
CloseHandle(native_);
|
|
||||||
#endif
|
|
||||||
native_ = handle::invalid_handle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
native_type native() const
|
|
||||||
{
|
|
||||||
return native_;
|
|
||||||
}
|
|
||||||
|
|
||||||
native_type release()
|
|
||||||
{
|
|
||||||
native_type native = native_;
|
|
||||||
native_ = handle::invalid_handle();
|
|
||||||
return native;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
native_type native_;
|
|
||||||
close_type close_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of handle to store native handle value.
|
|
||||||
*
|
|
||||||
* A shared pointer is used as handles represent system resources. If a
|
|
||||||
* handle is closed and becomes invalid the state of copies of the handle
|
|
||||||
* object will be updated as they all share the handle implementation.
|
|
||||||
*/
|
|
||||||
boost::shared_ptr<impl> impl_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constant function representing an invalid handle value.
|
|
||||||
*
|
|
||||||
* Returns the platform-specific handle value that represents an
|
|
||||||
* invalid handle. This is a constant function rather than a regular
|
|
||||||
* constant because, in the latter case, we cannot define it under
|
|
||||||
* Windows due to the value being of a complex type.
|
|
||||||
*/
|
|
||||||
static const native_type invalid_handle()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
return -1;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,439 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/operations.hpp
|
|
||||||
*
|
|
||||||
* Provides miscellaneous free functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_OPERATIONS_HPP
|
|
||||||
#define BOOST_PROCESS_OPERATIONS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <boost/process/detail/posix_helpers.hpp>
|
|
||||||
# include <utility>
|
|
||||||
# include <cstddef>
|
|
||||||
# include <stdlib.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# if defined(__CYGWIN__)
|
|
||||||
# include <boost/scoped_array.hpp>
|
|
||||||
# include <sys/cygwin.h>
|
|
||||||
# endif
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <boost/process/detail/windows_helpers.hpp>
|
|
||||||
# include <boost/scoped_array.hpp>
|
|
||||||
# include <boost/shared_array.hpp>
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/child.hpp>
|
|
||||||
#include <boost/process/context.hpp>
|
|
||||||
#include <boost/process/stream_id.hpp>
|
|
||||||
#include <boost/process/stream_ends.hpp>
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <boost/filesystem/path.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
|
||||||
#include <boost/system/system_error.hpp>
|
|
||||||
#include <boost/throw_exception.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locates the executable program \a file in all the directory components
|
|
||||||
* specified in \a path. If \a path is empty, the value of the PATH
|
|
||||||
* environment variable is used.
|
|
||||||
*
|
|
||||||
* The path variable is interpreted following the same conventions used
|
|
||||||
* to parse the PATH environment variable in the underlying platform.
|
|
||||||
*
|
|
||||||
* \throw boost::filesystem::filesystem_error If the file cannot be found
|
|
||||||
* in the path.
|
|
||||||
*/
|
|
||||||
inline std::string find_executable_in_path(const std::string &file,
|
|
||||||
std::string path = "")
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
BOOST_ASSERT(file.find('/') == std::string::npos);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
BOOST_ASSERT(file.find_first_of("\\/") == std::string::npos);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
const char *envpath = getenv("PATH");
|
|
||||||
if (!envpath)
|
|
||||||
boost::throw_exception(boost::filesystem::filesystem_error(
|
|
||||||
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
|
|
||||||
boost::system::errc::make_error_code(
|
|
||||||
boost::system::errc::no_such_file_or_directory)));
|
|
||||||
path = envpath;
|
|
||||||
}
|
|
||||||
BOOST_ASSERT(!path.empty());
|
|
||||||
|
|
||||||
#if defined(__CYGWIN__)
|
|
||||||
if (!cygwin_posix_path_list_p(path.c_str()))
|
|
||||||
{
|
|
||||||
int size = cygwin_win32_to_posix_path_list_buf_size(path.c_str());
|
|
||||||
boost::scoped_array<char> cygpath(new char[size]);
|
|
||||||
cygwin_win32_to_posix_path_list(path.c_str(), cygpath.get());
|
|
||||||
path = cygpath.get();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
std::string::size_type pos1 = 0, pos2;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pos2 = path.find(':', pos1);
|
|
||||||
std::string dir = (pos2 != std::string::npos) ?
|
|
||||||
path.substr(pos1, pos2 - pos1) : path.substr(pos1);
|
|
||||||
std::string f = dir +
|
|
||||||
(boost::algorithm::ends_with(dir, "/") ? "" : "/") + file;
|
|
||||||
if (!access(f.c_str(), X_OK))
|
|
||||||
result = f;
|
|
||||||
pos1 = pos2 + 1;
|
|
||||||
} while (pos2 != std::string::npos && result.empty());
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
const char *exts[] = { "", ".exe", ".com", ".bat", NULL };
|
|
||||||
const char **ext = exts;
|
|
||||||
while (*ext)
|
|
||||||
{
|
|
||||||
char buf[MAX_PATH];
|
|
||||||
char *dummy;
|
|
||||||
DWORD size = SearchPathA(path.empty() ? NULL : path.c_str(),
|
|
||||||
file.c_str(), *ext, MAX_PATH, buf, &dummy);
|
|
||||||
BOOST_ASSERT(size < MAX_PATH);
|
|
||||||
if (size > 0)
|
|
||||||
{
|
|
||||||
result = buf;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
++ext;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (result.empty())
|
|
||||||
boost::throw_exception(boost::filesystem::filesystem_error(
|
|
||||||
BOOST_PROCESS_SOURCE_LOCATION "file not found", file,
|
|
||||||
boost::system::errc::make_error_code(
|
|
||||||
boost::system::errc::no_such_file_or_directory)));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the program name from a given executable.
|
|
||||||
*
|
|
||||||
* \return The program name. On Windows the program name
|
|
||||||
* is returned without a file extension.
|
|
||||||
*/
|
|
||||||
inline std::string executable_to_progname(const std::string &exe)
|
|
||||||
{
|
|
||||||
std::string::size_type begin = 0;
|
|
||||||
std::string::size_type end = std::string::npos;
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
std::string::size_type slash = exe.rfind('/');
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
std::string::size_type slash = exe.find_last_of("/\\");
|
|
||||||
#endif
|
|
||||||
if (slash != std::string::npos)
|
|
||||||
begin = slash + 1;
|
|
||||||
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
if (exe.size() > 4 && (boost::algorithm::iends_with(exe, ".exe") ||
|
|
||||||
boost::algorithm::iends_with(exe, ".com") ||
|
|
||||||
boost::algorithm::iends_with(exe, ".bat")))
|
|
||||||
end = exe.size() - 4;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return exe.substr(begin, end - begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a new child process.
|
|
||||||
*
|
|
||||||
* Launches a new process based on the binary image specified by the
|
|
||||||
* executable, the set of arguments passed to it and the execution context.
|
|
||||||
*
|
|
||||||
* \remark Blocking remarks: This function may block if the device holding the
|
|
||||||
* executable blocks when loading the image. This might happen if, e.g.,
|
|
||||||
* the binary is being loaded from a network share.
|
|
||||||
*
|
|
||||||
* \return A handle to the new child process.
|
|
||||||
*/
|
|
||||||
template <typename Arguments, typename Context>
|
|
||||||
inline child create_child(const std::string &executable, Arguments args,
|
|
||||||
Context ctx)
|
|
||||||
{
|
|
||||||
typedef std::map<stream_id, stream_ends> handles_t;
|
|
||||||
handles_t handles;
|
|
||||||
typename Context::streams_t::iterator it = ctx.streams.begin();
|
|
||||||
for (; it != ctx.streams.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->first == stdin_id)
|
|
||||||
handles[it->first] = it->second(input_stream);
|
|
||||||
else if (it->first == stdout_id)
|
|
||||||
handles[it->first] = it->second(output_stream);
|
|
||||||
else if (it->first == stderr_id)
|
|
||||||
handles[it->first] = it->second(output_stream);
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
else
|
|
||||||
handles[it->first] = it->second(unknown_stream);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string p_name = ctx.process_name.empty() ?
|
|
||||||
executable_to_progname(executable) : ctx.process_name;
|
|
||||||
args.insert(args.begin(), p_name);
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
// Between fork() and execve() only async-signal-safe functions
|
|
||||||
// must be called if multithreaded applications should be supported.
|
|
||||||
// That's why the following code is executed before fork() is called.
|
|
||||||
#if defined(F_MAXFD)
|
|
||||||
int maxdescs = fcntl(-1, F_MAXFD, 0);
|
|
||||||
if (maxdescs == -1)
|
|
||||||
maxdescs = sysconf(_SC_OPEN_MAX);
|
|
||||||
#else
|
|
||||||
int maxdescs = sysconf(_SC_OPEN_MAX);
|
|
||||||
#endif
|
|
||||||
if (maxdescs == -1)
|
|
||||||
maxdescs = 1024;
|
|
||||||
std::vector<bool> closeflags(maxdescs, true);
|
|
||||||
std::pair<std::size_t, char**> argv = detail::collection_to_argv(args);
|
|
||||||
std::pair<std::size_t, char**> envp =
|
|
||||||
detail::environment_to_envp(ctx.env);
|
|
||||||
|
|
||||||
const char *work_dir = ctx.work_dir.c_str();
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (pid == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed");
|
|
||||||
else if (pid == 0)
|
|
||||||
{
|
|
||||||
if (chdir(work_dir) == -1)
|
|
||||||
{
|
|
||||||
auto r = write(STDERR_FILENO, "chdir() failed\n", 15);
|
|
||||||
if( r || !r ) _exit(127);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (handles_t::iterator it = handles.begin(); it != handles.end();
|
|
||||||
++it)
|
|
||||||
{
|
|
||||||
if (it->second.child.valid())
|
|
||||||
{
|
|
||||||
handles_t::iterator it2 = it;
|
|
||||||
++it2;
|
|
||||||
for (; it2 != handles.end(); ++it2)
|
|
||||||
{
|
|
||||||
if (it2->second.child.native() == it->first)
|
|
||||||
{
|
|
||||||
int fd = fcntl(it2->second.child.native(), F_DUPFD,
|
|
||||||
it->first + 1);
|
|
||||||
if (fd == -1)
|
|
||||||
{
|
|
||||||
auto r = write(STDERR_FILENO, "chdir() failed\n", 15);
|
|
||||||
(void)r;
|
|
||||||
_exit(127);
|
|
||||||
}
|
|
||||||
it2->second.child = fd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dup2(it->second.child.native(), it->first) == -1)
|
|
||||||
{
|
|
||||||
auto r = write(STDERR_FILENO, "chdir() failed\n", 15);
|
|
||||||
if( r || !r ) _exit(127);
|
|
||||||
}
|
|
||||||
closeflags[it->first] = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx.setup)
|
|
||||||
ctx.setup();
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < closeflags.size(); ++i)
|
|
||||||
{
|
|
||||||
if (closeflags[i])
|
|
||||||
close(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
execve(executable.c_str(), argv.second, envp.second);
|
|
||||||
|
|
||||||
// Actually we should delete argv and envp data. As we must not
|
|
||||||
// call any non-async-signal-safe functions though we simply exit.
|
|
||||||
auto r = write(STDERR_FILENO, "execve() failed\n", 16);
|
|
||||||
if( r || !r ) _exit(127);
|
|
||||||
_exit(127);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BOOST_ASSERT(pid > 0);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < argv.first; ++i)
|
|
||||||
delete[] argv.second[i];
|
|
||||||
delete[] argv.second;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < envp.first; ++i)
|
|
||||||
delete[] envp.second[i];
|
|
||||||
delete[] envp.second;
|
|
||||||
|
|
||||||
std::map<stream_id, handle> parent_ends;
|
|
||||||
for (handles_t::iterator it = handles.begin(); it != handles.end();
|
|
||||||
++it)
|
|
||||||
parent_ends[it->first] = it->second.parent;
|
|
||||||
|
|
||||||
return child(pid, parent_ends);
|
|
||||||
}
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
STARTUPINFOA startup_info;
|
|
||||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
|
||||||
startup_info.cb = sizeof(startup_info);
|
|
||||||
startup_info.dwFlags |= STARTF_USESTDHANDLES;
|
|
||||||
startup_info.hStdInput = handles[stdin_id].child.native();
|
|
||||||
startup_info.hStdOutput = handles[stdout_id].child.native();
|
|
||||||
startup_info.hStdError = handles[stderr_id].child.native();
|
|
||||||
|
|
||||||
if (ctx.setup)
|
|
||||||
ctx.setup(startup_info);
|
|
||||||
|
|
||||||
PROCESS_INFORMATION pi;
|
|
||||||
ZeroMemory(&pi, sizeof(pi));
|
|
||||||
|
|
||||||
boost::shared_array<char> cmdline =
|
|
||||||
detail::collection_to_windows_cmdline(args);
|
|
||||||
|
|
||||||
boost::scoped_array<char> exe(new char[executable.size() + 1]);
|
|
||||||
#if (BOOST_MSVC >= 1400)
|
|
||||||
strcpy_s(exe.get(), executable.size() + 1, executable.c_str());
|
|
||||||
#else
|
|
||||||
strcpy(exe.get(), executable.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::scoped_array<char> workdir(new char[ctx.work_dir.size() + 1]);
|
|
||||||
#if (BOOST_MSVC >= 1400)
|
|
||||||
strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str());
|
|
||||||
#else
|
|
||||||
strcpy(workdir.get(), ctx.work_dir.c_str());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
boost::shared_array<char> envstrs =
|
|
||||||
detail::environment_to_windows_strings(ctx.env);
|
|
||||||
|
|
||||||
DWORD creation_flags = 0;
|
|
||||||
if (ctx.suppress_console)
|
|
||||||
creation_flags |= CREATE_NO_WINDOW;
|
|
||||||
|
|
||||||
if (CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, creation_flags,
|
|
||||||
envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
|
|
||||||
|
|
||||||
handle hprocess(pi.hProcess);
|
|
||||||
|
|
||||||
if (!CloseHandle(pi.hThread))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
|
||||||
|
|
||||||
std::map<stream_id, handle> parent_ends;
|
|
||||||
parent_ends[stdin_id] = handles[stdin_id].parent;
|
|
||||||
parent_ends[stdout_id] = handles[stdout_id].parent;
|
|
||||||
parent_ends[stderr_id] = handles[stderr_id].parent;
|
|
||||||
|
|
||||||
return child(hprocess, parent_ends);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \overload
|
|
||||||
*/
|
|
||||||
inline child create_child(const std::string &executable)
|
|
||||||
{
|
|
||||||
return create_child(executable, std::vector<std::string>(), context());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \overload
|
|
||||||
*/
|
|
||||||
template <typename Arguments>
|
|
||||||
inline child create_child(const std::string &executable, Arguments args)
|
|
||||||
{
|
|
||||||
return create_child(executable, args, context());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a shell-based command.
|
|
||||||
*
|
|
||||||
* Executes the given command through the default system shell. The
|
|
||||||
* command is subject to pattern expansion, redirection and pipelining.
|
|
||||||
* The shell is launched as described by the parameters in the context.
|
|
||||||
*
|
|
||||||
* This function behaves similarly to the system(3) system call. In a
|
|
||||||
* POSIX system, the command is fed to /bin/sh whereas under a Windows
|
|
||||||
* system, it is fed to cmd.exe. It is difficult to write portable
|
|
||||||
* commands, but this function comes in handy in multiple situations.
|
|
||||||
*
|
|
||||||
* \remark Blocking remarks: This function may block if the device holding the
|
|
||||||
* executable blocks when loading the image. This might happen if, e.g.,
|
|
||||||
* the binary is being loaded from a network share.
|
|
||||||
*
|
|
||||||
* \return A handle to the new child process.
|
|
||||||
*/
|
|
||||||
template <typename Context>
|
|
||||||
inline child shell(const std::string &command, Context ctx)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
std::string executable = "/bin/sh";
|
|
||||||
std::vector<std::string> args;
|
|
||||||
args.push_back("-c");
|
|
||||||
args.push_back(command);
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
char sysdir[MAX_PATH];
|
|
||||||
UINT size = GetSystemDirectoryA(sysdir, sizeof(sysdir));
|
|
||||||
if (!size)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetSystemDirectory() failed");
|
|
||||||
std::string executable = std::string(sysdir) +
|
|
||||||
(sysdir[size - 1] != '\\' ? "\\cmd.exe" : "cmd.exe");
|
|
||||||
std::vector<std::string> args;
|
|
||||||
args.push_back("/c");
|
|
||||||
args.push_back(command);
|
|
||||||
#endif
|
|
||||||
return create_child(executable, args, ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \overload
|
|
||||||
*/
|
|
||||||
inline child shell(const std::string &command)
|
|
||||||
{
|
|
||||||
return shell(command, context());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/pid_type.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the pid type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_PID_TYPE_HPP
|
|
||||||
#define BOOST_PROCESS_PID_TYPE_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <sys/types.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Opaque name for the process identifier type.
|
|
||||||
*
|
|
||||||
* Each operating system identifies processes using a specific type.
|
|
||||||
* The \a pid_type type is used to transparently refer to a process
|
|
||||||
* regardless of the operating system.
|
|
||||||
*
|
|
||||||
* This type is guaranteed to be an integral type on all supported
|
|
||||||
* platforms. On POSIX systems it is defined as pid_t, on Windows systems as
|
|
||||||
* DWORD.
|
|
||||||
*/
|
|
||||||
typedef NativeProcessId pid_type;
|
|
||||||
#elif defined(BOOST_POSIX_API)
|
|
||||||
typedef pid_t pid_type;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef DWORD pid_type;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
49
vendor/boost_1.51/include/boost/process/pipe.hpp
vendored
49
vendor/boost_1.51/include/boost/process/pipe.hpp
vendored
|
|
@ -1,49 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/pipe.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the pipe class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_PIPE_HPP
|
|
||||||
#define BOOST_PROCESS_PIPE_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* The pipe class is a type definition for stream-based classes defined by
|
|
||||||
* Boost.Asio.
|
|
||||||
*
|
|
||||||
* The type definition is provided for convenience. You can also use Boost.Asio
|
|
||||||
* classes directly for asynchronous I/O operations.
|
|
||||||
*/
|
|
||||||
typedef BoostAsioPipe pipe;
|
|
||||||
#elif defined(BOOST_POSIX_API)
|
|
||||||
typedef boost::asio::posix::stream_descriptor pipe;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef boost::asio::windows::stream_handle pipe;
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
114
vendor/boost_1.51/include/boost/process/pistream.hpp
vendored
114
vendor/boost_1.51/include/boost/process/pistream.hpp
vendored
|
|
@ -1,114 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/pistream.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the pistream class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_PISTREAM_HPP
|
|
||||||
#define BOOST_PROCESS_PISTREAM_HPP
|
|
||||||
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <boost/process/detail/systembuf.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <istream>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Child process' output stream.
|
|
||||||
*
|
|
||||||
* The pistream class represents an output communication channel with the
|
|
||||||
* child process. The child process writes data to this stream and the
|
|
||||||
* parent process can read it through the pistream object. In other
|
|
||||||
* words, from the child's point of view, the communication channel is an
|
|
||||||
* output one, but from the parent's point of view it is an input one;
|
|
||||||
* hence the confusing pistream name.
|
|
||||||
*
|
|
||||||
* pistream objects cannot be copied because they buffer data
|
|
||||||
* that flows through the communication channel.
|
|
||||||
*
|
|
||||||
* A pistream object behaves as a std::istream stream in all senses.
|
|
||||||
* The class is only provided because it must provide a method to let
|
|
||||||
* the caller explicitly close the communication channel.
|
|
||||||
*
|
|
||||||
* \remark Blocking remarks: Functions that read data from this
|
|
||||||
* stream can block if the associated handle blocks during
|
|
||||||
* the read. As this class is used to communicate with child
|
|
||||||
* processes through anonymous pipes, the most typical blocking
|
|
||||||
* condition happens when the child has no more data to send to
|
|
||||||
* the pipe's system buffer. When this happens, the buffer
|
|
||||||
* eventually empties and the system blocks until the writer
|
|
||||||
* generates some data.
|
|
||||||
*/
|
|
||||||
class pistream : public std::istream, public boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a new process' output stream.
|
|
||||||
*/
|
|
||||||
explicit pistream(boost::process::handle h)
|
|
||||||
: std::istream(0),
|
|
||||||
handle_(h),
|
|
||||||
systembuf_(handle_.native())
|
|
||||||
{
|
|
||||||
rdbuf(&systembuf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the handle managed by this stream.
|
|
||||||
*/
|
|
||||||
const boost::process::handle &handle() const
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the handle managed by this stream.
|
|
||||||
*/
|
|
||||||
boost::process::handle &handle()
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the handle managed by this stream.
|
|
||||||
*
|
|
||||||
* Explicitly closes the handle managed by this stream. This
|
|
||||||
* function can be used by the user to tell the child process it's
|
|
||||||
* not willing to receive more data.
|
|
||||||
*/
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
handle_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* The handle managed by this stream.
|
|
||||||
*/
|
|
||||||
boost::process::handle handle_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The systembuf object used to manage this stream's data.
|
|
||||||
*/
|
|
||||||
detail::systembuf systembuf_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
115
vendor/boost_1.51/include/boost/process/postream.hpp
vendored
115
vendor/boost_1.51/include/boost/process/postream.hpp
vendored
|
|
@ -1,115 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/postream.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the postream class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_POSTREAM_HPP
|
|
||||||
#define BOOST_PROCESS_POSTREAM_HPP
|
|
||||||
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <boost/process/detail/systembuf.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Child process' input stream.
|
|
||||||
*
|
|
||||||
* The postream class represents an input communication channel with the
|
|
||||||
* child process. The child process reads data from this stream and the
|
|
||||||
* parent process can write to it through the postream object. In other
|
|
||||||
* words, from the child's point of view, the communication channel is an
|
|
||||||
* input one, but from the parent's point of view it is an output one;
|
|
||||||
* hence the confusing postream name.
|
|
||||||
*
|
|
||||||
* postream objects cannot be copied because they buffer data that flows
|
|
||||||
* through the communication channel.
|
|
||||||
*
|
|
||||||
* A postream object behaves as a std::ostream stream in all senses.
|
|
||||||
* The class is only provided because it must provide a method to let
|
|
||||||
* the caller explicitly close the communication channel.
|
|
||||||
*
|
|
||||||
* \remark Blocking remarks: Functions that write data to this
|
|
||||||
* stream can block if the associated handle blocks during
|
|
||||||
* the write. As this class is used to communicate with child
|
|
||||||
* processes through anonymous pipes, the most typical blocking
|
|
||||||
* condition happens when the child is not processing the data
|
|
||||||
* in the pipe's system buffer. When this happens, the buffer
|
|
||||||
* eventually fills up and the system blocks until the reader
|
|
||||||
* consumes some data, leaving some new room.
|
|
||||||
*/
|
|
||||||
class postream : public std::ostream, public boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Creates a new process' input stream.
|
|
||||||
*/
|
|
||||||
explicit postream(boost::process::handle h)
|
|
||||||
: std::ostream(0),
|
|
||||||
handle_(h),
|
|
||||||
systembuf_(handle_.native())
|
|
||||||
{
|
|
||||||
rdbuf(&systembuf_);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the handle managed by this stream.
|
|
||||||
*/
|
|
||||||
const boost::process::handle &handle() const
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the handle managed by this stream.
|
|
||||||
*/
|
|
||||||
boost::process::handle &handle()
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the handle managed by this stream.
|
|
||||||
*
|
|
||||||
* Explicitly closes the handle managed by this stream. This
|
|
||||||
* function can be used by the user to tell the child process there
|
|
||||||
* is no more data to send.
|
|
||||||
*/
|
|
||||||
void close()
|
|
||||||
{
|
|
||||||
systembuf_.sync();
|
|
||||||
handle_.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* The handle managed by this stream.
|
|
||||||
*/
|
|
||||||
boost::process::handle handle_;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The systembuf object used to manage this stream's data.
|
|
||||||
*/
|
|
||||||
detail::systembuf systembuf_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
213
vendor/boost_1.51/include/boost/process/process.hpp
vendored
213
vendor/boost_1.51/include/boost/process/process.hpp
vendored
|
|
@ -1,213 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/process.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the process class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_PROCESS_HPP
|
|
||||||
#define BOOST_PROCESS_PROCESS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <signal.h>
|
|
||||||
# include <sys/wait.h>
|
|
||||||
# include <errno.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <boost/process/handle.hpp>
|
|
||||||
# include <cstdlib>
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/pid_type.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process class to represent any running process.
|
|
||||||
*/
|
|
||||||
class process
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Constructs a new process object.
|
|
||||||
*
|
|
||||||
* Creates a new process object that represents a running process
|
|
||||||
* within the system.
|
|
||||||
*
|
|
||||||
* On Windows the process is opened and a handle saved. This is required
|
|
||||||
* to avoid the operating system removing process resources when the
|
|
||||||
* process exits. The handle is closed when the process instance (and all
|
|
||||||
* of its copies) is destroyed.
|
|
||||||
*/
|
|
||||||
process(pid_type id)
|
|
||||||
: id_(id)
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
, handle_(open_process(id))
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Constructs a new process object.
|
|
||||||
*
|
|
||||||
* Creates a new process object that represents a running process
|
|
||||||
* within the system.
|
|
||||||
*
|
|
||||||
* This operation is only available on Windows systems. The handle is
|
|
||||||
* closed when the process instance (and all of its copies) is destroyed.
|
|
||||||
*/
|
|
||||||
process(handle h)
|
|
||||||
: id_(GetProcessId(h.native())),
|
|
||||||
handle_(h)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the process identifier.
|
|
||||||
*/
|
|
||||||
pid_type get_id() const
|
|
||||||
{
|
|
||||||
return id_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Terminates the process execution.
|
|
||||||
*
|
|
||||||
* Forces the termination of the process execution. Some platforms
|
|
||||||
* allow processes to ignore some external termination notifications
|
|
||||||
* or to capture them for a proper exit cleanup. You can set the
|
|
||||||
* \a force flag to true to force their termination regardless
|
|
||||||
* of any exit handler.
|
|
||||||
*
|
|
||||||
* After this call, accessing this object can be dangerous because the
|
|
||||||
* process identifier may have been reused by a different process. It
|
|
||||||
* might still be valid, though, if the process has refused to die.
|
|
||||||
*
|
|
||||||
* \throw boost::system::system_error If system calls used to terminate the
|
|
||||||
* process fail.
|
|
||||||
*/
|
|
||||||
void terminate(bool force = false) const
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (kill(id_, force ? SIGKILL : SIGTERM) == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
#if defined(BOOST_MSVC)
|
|
||||||
force;
|
|
||||||
#endif
|
|
||||||
HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_);
|
|
||||||
if (h == NULL)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
|
||||||
if (!TerminateProcess(h, EXIT_FAILURE))
|
|
||||||
{
|
|
||||||
CloseHandle(h);
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
|
|
||||||
}
|
|
||||||
if (!CloseHandle(h))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blocks and waits for the process to terminate.
|
|
||||||
*
|
|
||||||
* Returns an exit code. The process object ceases to be valid after this
|
|
||||||
* call.
|
|
||||||
*
|
|
||||||
* \remark Blocking remarks: This call blocks if the process has not
|
|
||||||
* finalized execution and waits until it terminates.
|
|
||||||
*
|
|
||||||
* \throw boost::system::system_error If system calls used to wait for the
|
|
||||||
* process fail.
|
|
||||||
*/
|
|
||||||
int wait() const
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
pid_t p;
|
|
||||||
int status;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
p = waitpid(id_, &status, 0);
|
|
||||||
} while (p == -1 && errno == EINTR);
|
|
||||||
if (p == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
|
|
||||||
return status;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
|
|
||||||
id_);
|
|
||||||
if (h == NULL)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
|
||||||
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
|
|
||||||
{
|
|
||||||
CloseHandle(h);
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"WaitForSingleObject() failed");
|
|
||||||
}
|
|
||||||
DWORD exit_code;
|
|
||||||
if (!GetExitCodeProcess(h, &exit_code))
|
|
||||||
{
|
|
||||||
CloseHandle(h);
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"GetExitCodeProcess() failed");
|
|
||||||
}
|
|
||||||
if (!CloseHandle(h))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
|
||||||
return exit_code;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* The process identifier.
|
|
||||||
*/
|
|
||||||
pid_type id_;
|
|
||||||
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
/**
|
|
||||||
* Opens a process and returns a handle.
|
|
||||||
*
|
|
||||||
* OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure.
|
|
||||||
* That's why the return value is manually checked in this helper function
|
|
||||||
* instead of simply passing it to the constructor of the handle class.
|
|
||||||
*/
|
|
||||||
HANDLE open_process(pid_type id)
|
|
||||||
{
|
|
||||||
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id);
|
|
||||||
if (h == NULL)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* The process handle.
|
|
||||||
*/
|
|
||||||
handle handle_;
|
|
||||||
private:
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
188
vendor/boost_1.51/include/boost/process/self.hpp
vendored
188
vendor/boost_1.51/include/boost/process/self.hpp
vendored
|
|
@ -1,188 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/self.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the self class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_SELF_HPP
|
|
||||||
#define BOOST_PROCESS_SELF_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <boost/scoped_array.hpp>
|
|
||||||
# include <errno.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
# include <limits.h>
|
|
||||||
# if defined(__APPLE__)
|
|
||||||
# include <crt_externs.h>
|
|
||||||
# endif
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
#else
|
|
||||||
# error "Unsupported platform."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/process.hpp>
|
|
||||||
#include <boost/process/environment.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
extern char **environ;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The self class provides access to the process itself.
|
|
||||||
*/
|
|
||||||
class self : public process, public boost::noncopyable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Returns the self instance representing the caller's process.
|
|
||||||
*/
|
|
||||||
static self &get_instance()
|
|
||||||
{
|
|
||||||
static self *instance = 0;
|
|
||||||
if (!instance)
|
|
||||||
instance = new self;
|
|
||||||
return *instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current environment.
|
|
||||||
*
|
|
||||||
* Returns the current process environment variables. Modifying the
|
|
||||||
* returned object has no effect on the current environment.
|
|
||||||
*/
|
|
||||||
static environment get_environment()
|
|
||||||
{
|
|
||||||
environment e;
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# if defined(__APPLE__)
|
|
||||||
char **env = *_NSGetEnviron();
|
|
||||||
# else
|
|
||||||
char **env = environ;
|
|
||||||
# endif
|
|
||||||
|
|
||||||
while (*env)
|
|
||||||
{
|
|
||||||
std::string s = *env;
|
|
||||||
std::string::size_type pos = s.find('=');
|
|
||||||
e.insert(environment::value_type(s.substr(0, pos),
|
|
||||||
s.substr(pos + 1)));
|
|
||||||
++env;
|
|
||||||
}
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# ifdef GetEnvironmentStrings
|
|
||||||
# undef GetEnvironmentStrings
|
|
||||||
# endif
|
|
||||||
|
|
||||||
char *ms_environ = GetEnvironmentStrings();
|
|
||||||
if (!ms_environ)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"GetEnvironmentStrings() failed");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
char *env = ms_environ;
|
|
||||||
while (*env)
|
|
||||||
{
|
|
||||||
std::string s = env;
|
|
||||||
std::string::size_type pos = s.find('=');
|
|
||||||
e.insert(environment::value_type(s.substr(0, pos),
|
|
||||||
s.substr(pos + 1)));
|
|
||||||
env += s.size() + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
FreeEnvironmentStringsA(ms_environ);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
FreeEnvironmentStringsA(ms_environ);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current work directory.
|
|
||||||
*/
|
|
||||||
static std::string get_work_dir()
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
#if defined(PATH_MAX)
|
|
||||||
char buffer[PATH_MAX];
|
|
||||||
char *cwd = buffer;
|
|
||||||
long size = PATH_MAX;
|
|
||||||
#elif defined(_PC_PATH_MAX)
|
|
||||||
errno = 0;
|
|
||||||
long size = pathconf("/", _PC_PATH_MAX);
|
|
||||||
if (size == -1 && errno)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed");
|
|
||||||
else if (size == -1)
|
|
||||||
size = BOOST_PROCESS_POSIX_PATH_MAX;
|
|
||||||
BOOST_ASSERT(size > 0);
|
|
||||||
boost::scoped_array<char> buffer(new char[size]);
|
|
||||||
char *cwd = buffer.get();
|
|
||||||
#else
|
|
||||||
char buffer[BOOST_PROCESS_POSIX_PATH_MAX];
|
|
||||||
char *cwd = buffer;
|
|
||||||
long size = BOOST_PROCESS_POSIX_PATH_MAX;
|
|
||||||
#endif
|
|
||||||
if (!getcwd(cwd, size))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed");
|
|
||||||
BOOST_ASSERT(cwd[0] != '\0');
|
|
||||||
return cwd;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
BOOST_ASSERT(MAX_PATH > 0);
|
|
||||||
char cwd[MAX_PATH];
|
|
||||||
if (!GetCurrentDirectoryA(sizeof(cwd), cwd))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"GetCurrentDirectory() failed");
|
|
||||||
BOOST_ASSERT(cwd[0] != '\0');
|
|
||||||
return cwd;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Constructs a new self object.
|
|
||||||
*
|
|
||||||
* Creates a new self object that represents the current process.
|
|
||||||
*/
|
|
||||||
self() :
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
process(getpid())
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
process(GetCurrentProcessId())
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/status.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the status class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_STATUS_HPP
|
|
||||||
#define BOOST_PROCESS_STATUS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/process/detail/basic_status.hpp>
|
|
||||||
#include <boost/process/detail/basic_status_service.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The status class to wait for processes to exit.
|
|
||||||
*
|
|
||||||
* The status class is a Boost.Asio I/O object and supports synchronous
|
|
||||||
* and asynchronous wait operations.
|
|
||||||
*/
|
|
||||||
typedef detail::basic_status<detail::basic_status_service<> > status;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,326 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/stream_behavior.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of stream behavior classes.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_STREAM_BEHAVIOR_HPP
|
|
||||||
#define BOOST_PROCESS_STREAM_BEHAVIOR_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
# include <sys/stat.h>
|
|
||||||
# include <fcntl.h>
|
|
||||||
# include <unistd.h>
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
# include <windows.h>
|
|
||||||
# include <rpc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <boost/process/stream_ends.hpp>
|
|
||||||
#include <boost/process/stream_type.hpp>
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
namespace behavior {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to close streams of a child process.
|
|
||||||
*
|
|
||||||
* A child process will not be able to use the stream.
|
|
||||||
*/
|
|
||||||
class close
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
stream_ends operator()(stream_type) const
|
|
||||||
{
|
|
||||||
return stream_ends();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to make a child process inherit streams.
|
|
||||||
*
|
|
||||||
* A child process will use the very same stream of its parent process.
|
|
||||||
*/
|
|
||||||
class inherit
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
inherit(handle::native_type h)
|
|
||||||
: h_(h, handle::dont_close)
|
|
||||||
{
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
if (h != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
|
||||||
if (!SetHandleInformation(h_.native(), HANDLE_FLAG_INHERIT,
|
|
||||||
HANDLE_FLAG_INHERIT))
|
|
||||||
{
|
|
||||||
HANDLE proc = GetCurrentProcess();
|
|
||||||
HANDLE dup;
|
|
||||||
if (!DuplicateHandle(proc, h_.native(), proc, &dup, 0,
|
|
||||||
TRUE, DUPLICATE_SAME_ACCESS))
|
|
||||||
{
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"DuplicateHandle() failed");
|
|
||||||
}
|
|
||||||
h_ = dup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
stream_ends operator()(stream_type) const
|
|
||||||
{
|
|
||||||
return stream_ends(h_, handle());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
handle h_;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to redirect streams with a pipe.
|
|
||||||
*
|
|
||||||
* A child process will be able to communicate with its parent process.
|
|
||||||
*/
|
|
||||||
class pipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
pipe()
|
|
||||||
: stype_(unknown_stream)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
pipe(stream_type stype)
|
|
||||||
: stype_(stype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stream_ends operator()(stream_type stype) const
|
|
||||||
{
|
|
||||||
handle::native_type ends[2];
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (::pipe(ends) == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed");
|
|
||||||
if (stype_ != unknown_stream)
|
|
||||||
stype = stype_;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
ZeroMemory(&sa, sizeof(sa));
|
|
||||||
sa.nLength = sizeof(sa);
|
|
||||||
sa.lpSecurityDescriptor = NULL;
|
|
||||||
sa.bInheritHandle = FALSE;
|
|
||||||
if (!CreatePipe(&ends[0], &ends[1], &sa, 0))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
|
|
||||||
#endif
|
|
||||||
handle child_end = ends[stype == input_stream ? 0 : 1];
|
|
||||||
handle parent_end = ends[stype == input_stream ? 1 : 0];
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
|
||||||
HANDLE_FLAG_INHERIT))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"SetHandleInformation() failed");
|
|
||||||
#endif
|
|
||||||
return stream_ends(child_end, parent_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
private:
|
|
||||||
stream_type stype_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to redirect streams with a named pipe.
|
|
||||||
*
|
|
||||||
* A child process will be able to communicate with its parent process.
|
|
||||||
*/
|
|
||||||
class named_pipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
named_pipe(const std::string &name)
|
|
||||||
: name_(name)
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
, stype_(unknown_stream)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
named_pipe(const std::string &name, stream_type stype)
|
|
||||||
: name_(name),
|
|
||||||
stype_(stype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stream_ends operator()(stream_type stype) const
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (mkfifo(name_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed");
|
|
||||||
handle child_end = open(name_.c_str(), O_RDONLY | O_NONBLOCK);
|
|
||||||
if (!child_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
|
||||||
int opts = fcntl(child_end.native(), F_GETFL);
|
|
||||||
if (opts == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
|
|
||||||
opts ^= O_NONBLOCK;
|
|
||||||
if (fcntl(child_end.native(), F_SETFL, opts) == -1)
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fcntl(2) failed");
|
|
||||||
handle parent_end = open(name_.c_str(), O_WRONLY);
|
|
||||||
if (!parent_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
|
||||||
if (stype_ != unknown_stream)
|
|
||||||
stype = stype_;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
SECURITY_ATTRIBUTES sa;
|
|
||||||
ZeroMemory(&sa, sizeof(sa));
|
|
||||||
sa.nLength = sizeof(sa);
|
|
||||||
sa.lpSecurityDescriptor = NULL;
|
|
||||||
sa.bInheritHandle = TRUE;
|
|
||||||
handle child_end = CreateNamedPipeA(name_.c_str(), PIPE_ACCESS_INBOUND |
|
|
||||||
FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
|
|
||||||
if (!child_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed");
|
|
||||||
handle parent_end = CreateFileA(name_.c_str(), GENERIC_WRITE, 0, NULL,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
||||||
if (!parent_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
|
|
||||||
#endif
|
|
||||||
if (stype == output_stream)
|
|
||||||
std::swap(child_end, parent_end);
|
|
||||||
#if defined(BOOST_WINDOWS_API)
|
|
||||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
|
||||||
HANDLE_FLAG_INHERIT))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"SetHandleInformation() failed");
|
|
||||||
#endif
|
|
||||||
return stream_ends(child_end, parent_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string name_;
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
stream_type stype_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to redirect streams with a pipe which supports asynchronous
|
|
||||||
* I/O.
|
|
||||||
*
|
|
||||||
* As platforms require different types of pipes for asynchronous I/O this
|
|
||||||
* stream behavior is provided for convenience. It uses the minimum required
|
|
||||||
* pipe type on a platform in order to be able to use asynchronous I/O.
|
|
||||||
*/
|
|
||||||
#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
typedef pipe async_pipe;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
class async_pipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
stream_ends operator()(stream_type stype) const
|
|
||||||
{
|
|
||||||
UUID uuid;
|
|
||||||
RPC_STATUS s = UuidCreateSequential(&uuid);
|
|
||||||
if (s != RPC_S_OK && s != RPC_S_UUID_LOCAL_ONLY)
|
|
||||||
BOOST_PROCESS_THROW_ERROR(s, "UuidCreateSequential() failed");
|
|
||||||
unsigned char *c;
|
|
||||||
s = UuidToStringA(&uuid, &c);
|
|
||||||
if (s != RPC_S_OK)
|
|
||||||
BOOST_PROCESS_THROW_ERROR(s, "UuidToString() failed");
|
|
||||||
std::string name;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
name = reinterpret_cast<char*>(c);
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
|
||||||
RpcStringFreeA(&c);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
RpcStringFreeA(&c);
|
|
||||||
named_pipe p("\\\\.\\pipe\\boost_process_" + name);
|
|
||||||
return p(stype);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream behavior to mute streams.
|
|
||||||
*
|
|
||||||
* A child process will be able to use streams. But data written to an
|
|
||||||
* output stream is discarded and data read from an input stream is 0.
|
|
||||||
*/
|
|
||||||
class null
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
null()
|
|
||||||
: stype_(unknown_stream)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
null(stream_type stype)
|
|
||||||
: stype_(stype)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stream_ends operator()(stream_type stype) const
|
|
||||||
{
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
if (stype_ != unknown_stream)
|
|
||||||
stype = stype_;
|
|
||||||
std::string filename = (stype == input_stream) ? "/dev/zero" :
|
|
||||||
"/dev/null";
|
|
||||||
int flag = (stype == input_stream) ? O_RDONLY : O_WRONLY;
|
|
||||||
handle child_end = open(filename.c_str(), flag);
|
|
||||||
if (!child_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
DWORD access = (stype == input_stream) ? GENERIC_READ : GENERIC_WRITE;
|
|
||||||
handle child_end = CreateFileA("NUL", access, 0, NULL, OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (!child_end.valid())
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
|
|
||||||
if (!SetHandleInformation(child_end.native(), HANDLE_FLAG_INHERIT,
|
|
||||||
HANDLE_FLAG_INHERIT))
|
|
||||||
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
|
|
||||||
"SetHandleInformation() failed");
|
|
||||||
#endif
|
|
||||||
return stream_ends(child_end, handle());
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
private:
|
|
||||||
stream_type stype_;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/stream_ends.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the stream_ends class.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_STREAM_ENDS_HPP
|
|
||||||
#define BOOST_PROCESS_STREAM_ENDS_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
#include <boost/process/handle.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A pair of handles to configure streams.
|
|
||||||
*
|
|
||||||
* Stream behaviors return a pair of handles to specify how a child's stream
|
|
||||||
* should be configured and possibly the opposite end of a child's end. This
|
|
||||||
* is the end remaining in the parent process and which can be used for example
|
|
||||||
* to communicate with a child process through its standard streams.
|
|
||||||
*/
|
|
||||||
struct stream_ends {
|
|
||||||
/**
|
|
||||||
* The child's end.
|
|
||||||
*/
|
|
||||||
handle child;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The parent's end.
|
|
||||||
*/
|
|
||||||
handle parent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard constructor creating two invalid handles.
|
|
||||||
*/
|
|
||||||
stream_ends()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper constructor to easily initialize handles.
|
|
||||||
*/
|
|
||||||
stream_ends(handle c, handle p)
|
|
||||||
: child(c),
|
|
||||||
parent(p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/stream_id.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the stream_id type.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_STREAM_ID_HPP
|
|
||||||
#define BOOST_PROCESS_STREAM_ID_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Standard stream id to refer to standard streams in a cross-platform manner.
|
|
||||||
*/
|
|
||||||
enum std_stream_id { stdin_id, stdout_id, stderr_id };
|
|
||||||
|
|
||||||
#if defined(BOOST_PROCESS_DOXYGEN)
|
|
||||||
/**
|
|
||||||
* Stream id type.
|
|
||||||
*
|
|
||||||
* Depending on the platform the stream id type is defined to refer to standard
|
|
||||||
* streams only or to support more streams.
|
|
||||||
*/
|
|
||||||
typedef NativeStreamId stream_id;
|
|
||||||
#elif defined(BOOST_POSIX_API)
|
|
||||||
typedef int stream_id;
|
|
||||||
#elif defined(BOOST_WINDOWS_API)
|
|
||||||
typedef std_stream_id stream_id;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
//
|
|
||||||
// Boost.Process
|
|
||||||
// ~~~~~~~~~~~~~
|
|
||||||
//
|
|
||||||
// Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
|
||||||
// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
|
||||||
// Copyright (c) 2009 Boris Schaeling
|
|
||||||
// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
|
||||||
//
|
|
||||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
||||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \file boost/process/stream_type.hpp
|
|
||||||
*
|
|
||||||
* Includes the declaration of the stream_type enumeration.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef BOOST_PROCESS_STREAM_TYPE_HPP
|
|
||||||
#define BOOST_PROCESS_STREAM_TYPE_HPP
|
|
||||||
|
|
||||||
#include <boost/process/config.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace process {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stream type to differentiate between input and output streams.
|
|
||||||
*
|
|
||||||
* On POSIX systems another value unknown_stream is defined. It is passed
|
|
||||||
* to stream behaviors for file descriptors greater than 2.
|
|
||||||
*/
|
|
||||||
enum stream_type {
|
|
||||||
input_stream,
|
|
||||||
output_stream
|
|
||||||
#if defined(BOOST_POSIX_API)
|
|
||||||
, unknown_stream
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
* *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10| 0x14| 0x18| 0x1c| 0x20| 0x24| *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | v1 | v2 | v3 | v4 | v5 | v6 | v7 | v8 | sp | lr | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 10 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0x28| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | pc | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 11 | 12 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0x2c| 0x30| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* |sbase|slimit| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0x34| 0x38|0x3c| 0x40| 0x44| 0x48| 0x4c| 0x50| 0x54| 0x58 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | s16 | s17 | s18 | s19 | s20 | s21 | s22 | s23 | s24 | s25 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 23 | 24 | 25 | 26 | 27 | 28 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0x5c| 0x60| 0x64| 0x68| 0x6c| 0x70| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | s26 | s27 | s28 | s29 | s30 | s31 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl jump_fcontext
|
|
||||||
.align 2
|
|
||||||
.type jump_fcontext,%function
|
|
||||||
jump_fcontext:
|
|
||||||
stmia a1, {v1-v8,sp-lr} @ save V1-V8,SP-LR
|
|
||||||
str lr, [a1,#40] @ save LR as PC
|
|
||||||
|
|
||||||
#if (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
|
||||||
cmp a4, #0 @ test if fpu env should be preserved
|
|
||||||
beq 1f
|
|
||||||
|
|
||||||
mov a4, a1
|
|
||||||
add a4, #52
|
|
||||||
fstmiax a4, {d8-d15} @ save S16-S31
|
|
||||||
|
|
||||||
mov a4, a2
|
|
||||||
add a4, #52
|
|
||||||
fldmiax a4, {d8-d15} @ restore S16-S31
|
|
||||||
1:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mov a1, a3 @ use third arg as return value after jump
|
|
||||||
@ and as first arg in context function
|
|
||||||
ldmia a2, {v1-v8,sp-pc} @ restore v1-V8,SP-PC
|
|
||||||
.size jump_fcontext,.-jump_fcontext
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl make_fcontext
|
|
||||||
.align 2
|
|
||||||
.type make_fcontext,%function
|
|
||||||
make_fcontext:
|
|
||||||
str a1, [a1,#0] @ save the address of passed context
|
|
||||||
str a2, [a1,#40] @ save address of the context function
|
|
||||||
ldr a2, [a1,#44] @ load the stack base
|
|
||||||
|
|
||||||
push {a1,lr} @ save pointer to fcontext_t
|
|
||||||
mov a1, a2 @ stack pointer as arg for align_stack
|
|
||||||
bl align_stack@PLT @ align stack
|
|
||||||
mov a2, a1 @ begin of aligned stack
|
|
||||||
pop {a1,lr} @ restore pointer to fcontext_t
|
|
||||||
|
|
||||||
str a2, [a1,#32] @ save the aligned stack base
|
|
||||||
|
|
||||||
adr a2, finish @ address of finish; called after context function returns
|
|
||||||
str a2, [a1,#36]
|
|
||||||
|
|
||||||
mov a1, #0
|
|
||||||
bx lr
|
|
||||||
|
|
||||||
finish:
|
|
||||||
mov a1, #0 @ exit code is zero
|
|
||||||
bl _exit@PLT @ exit application
|
|
||||||
.size make_fcontext,.-make_fcontext
|
|
||||||
|
|
@ -1,151 +0,0 @@
|
||||||
|
|
||||||
; Copyright Oliver Kowalke 2009.
|
|
||||||
; Distributed under the Boost Software License, Version 1.0.
|
|
||||||
; (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
; http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 0 | 1 | 2 | 3 | 4 | 5 |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 0h | 04h | 08h | 0ch | 010h | 014h |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | EDI | ESI | EBX | EBP | ESP | EIP |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 6 | 7 | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 018h | 01ch | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | ss_base | ss_limit| |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 8 | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 020h | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; |fc_execpt| |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 9 | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 024h | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; |fc_strage| |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 10 | 11 | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | 028h | 02ch | |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
; | fc_mxcsr|fc_x87_cw| |
|
|
||||||
; --------------------------------------------------------------
|
|
||||||
|
|
||||||
.386
|
|
||||||
.XMM
|
|
||||||
.model flat, c
|
|
||||||
_exit PROTO, value:SDWORD
|
|
||||||
align_stack PROTO, vp:DWORD
|
|
||||||
seh_fcontext PROTO, except:DWORD, frame:DWORD, context:DWORD, dispatch:DWORD
|
|
||||||
.code
|
|
||||||
|
|
||||||
jump_fcontext PROC EXPORT
|
|
||||||
mov ecx, [esp+04h] ; load address of the first fcontext_t arg
|
|
||||||
mov [ecx], edi ; save EDI
|
|
||||||
mov [ecx+04h], esi ; save ESI
|
|
||||||
mov [ecx+08h], ebx ; save EBX
|
|
||||||
mov [ecx+0ch], ebp ; save EBP
|
|
||||||
|
|
||||||
assume fs:nothing
|
|
||||||
mov edx, fs:[018h] ; load NT_TIB
|
|
||||||
assume fs:error
|
|
||||||
mov eax, [edx] ; load current SEH exception list
|
|
||||||
mov [ecx+020h], eax ; save current exception list
|
|
||||||
mov eax, [edx+04h] ; load current stack base
|
|
||||||
mov [ecx+018h], eax ; save current stack base
|
|
||||||
mov eax, [edx+08h] ; load current stack limit
|
|
||||||
mov [ecx+01ch], eax ; save current stack limit
|
|
||||||
mov eax, [edx+010h] ; load fiber local storage
|
|
||||||
mov [ecx+024h], eax ; save fiber local storage
|
|
||||||
|
|
||||||
lea eax, [esp+04h] ; exclude the return address
|
|
||||||
mov [ecx+010h], eax ; save as stack pointer
|
|
||||||
mov eax, [esp] ; load return address
|
|
||||||
mov [ecx+014h], eax ; save return address
|
|
||||||
|
|
||||||
mov edx, [esp+08h] ; load address of the second fcontext_t arg
|
|
||||||
mov edi, [edx] ; restore EDI
|
|
||||||
mov esi, [edx+04h] ; restore ESI
|
|
||||||
mov ebx, [edx+08h] ; restore EBX
|
|
||||||
mov ebp, [edx+0ch] ; restore EBP
|
|
||||||
|
|
||||||
mov eax, [esp+010h] ; check if fpu enve preserving was requested
|
|
||||||
test eax, eax
|
|
||||||
je nxt
|
|
||||||
|
|
||||||
stmxcsr [ecx+028h] ; save MMX control word
|
|
||||||
fnstcw [ecx+02ch] ; save x87 control word
|
|
||||||
ldmxcsr [edx+028h] ; restore MMX control word
|
|
||||||
fldcw [edx+02ch] ; restore x87 control word
|
|
||||||
nxt:
|
|
||||||
mov ecx, edx
|
|
||||||
assume fs:nothing
|
|
||||||
mov edx, fs:[018h] ; load NT_TIB
|
|
||||||
assume fs:error
|
|
||||||
mov eax, [ecx+020h] ; load SEH exception list
|
|
||||||
mov [edx], eax ; restore next SEH item
|
|
||||||
mov eax, [ecx+018h] ; load stack base
|
|
||||||
mov [edx+04h], eax ; restore stack base
|
|
||||||
mov eax, [ecx+01ch] ; load stack limit
|
|
||||||
mov [edx+08h], eax ; restore stack limit
|
|
||||||
mov eax, [ecx+024h] ; load fiber local storage
|
|
||||||
mov [edx+010h], eax ; restore fiber local storage
|
|
||||||
|
|
||||||
mov eax, [esp+0ch] ; use third arg as return value after jump
|
|
||||||
|
|
||||||
mov esp, [ecx+010h] ; restore ESP
|
|
||||||
mov [esp+04h], eax ; use third arg as first arg in context function
|
|
||||||
mov ecx, [ecx+014h] ; fetch the address to return to
|
|
||||||
|
|
||||||
jmp ecx ; indirect jump to context
|
|
||||||
jump_fcontext ENDP
|
|
||||||
|
|
||||||
make_fcontext PROC EXPORT
|
|
||||||
mov eax, [esp+04h] ; load address of the fcontext_t arg0
|
|
||||||
mov [eax], eax ; save the address of passed context
|
|
||||||
mov ecx, [esp+08h] ; load the address of the context function
|
|
||||||
mov [eax+014h], ecx ; save the address of the context function
|
|
||||||
mov edx, [eax+018h] ; load the stack base
|
|
||||||
|
|
||||||
push eax ; save pointer to fcontext_t
|
|
||||||
push edx ; stack pointer as arg for align_stack
|
|
||||||
call align_stack ; align stack
|
|
||||||
mov edx, eax ; begin of aligned stack
|
|
||||||
pop eax ; remove arg for align_stack
|
|
||||||
pop eax ; restore pointer to fcontext_t
|
|
||||||
|
|
||||||
lea edx, [edx-014h] ; reserve space for last frame on stack, (ESP + 4) & 15 == 0
|
|
||||||
mov [eax+010h], edx ; save the aligned stack
|
|
||||||
|
|
||||||
mov ecx, seh_fcontext ; set ECX to exception-handler
|
|
||||||
mov [edx+0ch], ecx ; save ECX as SEH handler
|
|
||||||
mov ecx, 0ffffffffh ; set ECX to -1
|
|
||||||
mov [edx+08h], ecx ; save ECX as next SEH item
|
|
||||||
lea ecx, [edx+08h] ; load address of next SEH item
|
|
||||||
mov [eax+02ch], ecx ; save next SEH
|
|
||||||
|
|
||||||
stmxcsr [eax+028h] ; save MMX control word
|
|
||||||
fnstcw [eax+02ch] ; save x87 control word
|
|
||||||
|
|
||||||
mov ecx, finish ; address of finish
|
|
||||||
mov [edx], ecx
|
|
||||||
|
|
||||||
xor eax, eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
xor eax, eax
|
|
||||||
push eax ; exit code is zero
|
|
||||||
call _exit ; exit application
|
|
||||||
hlt
|
|
||||||
make_fcontext ENDP
|
|
||||||
END
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 6 | 7 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x18 | 0x1c | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | sbase | slimit | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 8 | 9 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x20 | 0x24 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | fc_mxcsr|fc_x87_cw| | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl jump_fcontext
|
|
||||||
.align 2
|
|
||||||
.type jump_fcontext,@function
|
|
||||||
jump_fcontext:
|
|
||||||
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
|
|
||||||
movl %edi, (%ecx) /* save EDI */
|
|
||||||
movl %esi, 0x4(%ecx) /* save ESI */
|
|
||||||
movl %ebx, 0x8(%ecx) /* save EBX */
|
|
||||||
movl %ebp, 0xc(%ecx) /* save EBP */
|
|
||||||
|
|
||||||
leal 0x4(%esp), %eax /* exclude the return address */
|
|
||||||
movl %eax, 0x10(%ecx) /* save as stack pointer */
|
|
||||||
movl (%esp), %eax /* load return address */
|
|
||||||
movl %eax, 0x14(%ecx) /* save return address */
|
|
||||||
|
|
||||||
movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */
|
|
||||||
movl (%edx), %edi /* restore EDI */
|
|
||||||
movl 0x4(%edx), %esi /* restore ESI */
|
|
||||||
movl 0x8(%edx), %ebx /* restore EBX */
|
|
||||||
movl 0xc(%edx), %ebp /* restore EBP */
|
|
||||||
|
|
||||||
movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */
|
|
||||||
test %eax, %eax
|
|
||||||
je 1f
|
|
||||||
|
|
||||||
stmxcsr 0x20(%ecx) /* save MMX control and status word */
|
|
||||||
fnstcw 0x24(%ecx) /* save x87 control word */
|
|
||||||
ldmxcsr 0x20(%edx) /* restore MMX control and status word */
|
|
||||||
fldcw 0x24(%edx) /* restore x87 control word */
|
|
||||||
1:
|
|
||||||
movl 0xc(%esp), %eax /* use third arg as return value after jump */
|
|
||||||
|
|
||||||
movl 0x10(%edx), %esp /* restore ESP */
|
|
||||||
movl %eax, 0x4(%esp) /* use third arg as first arg in context function */
|
|
||||||
movl 0x14(%edx), %edx /* fetch the address to return to */
|
|
||||||
|
|
||||||
jmp *%edx /* indirect jump to context */
|
|
||||||
.size jump_fcontext,.-jump_fcontext
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl make_fcontext
|
|
||||||
.align 2
|
|
||||||
.type make_fcontext,@function
|
|
||||||
make_fcontext:
|
|
||||||
movl 0x4(%esp), %eax /* load address of the fcontext_t */
|
|
||||||
movl %eax, (%eax) /* save the address of current context */
|
|
||||||
movl 0x8(%esp), %ecx /* load the address of the context function */
|
|
||||||
movl %ecx, 0x14(%eax) /* save the address of the context function */
|
|
||||||
movl 0x18(%eax), %edx /* load the stack base */
|
|
||||||
|
|
||||||
pushl %eax /* save pointer to fcontext_t */
|
|
||||||
pushl %ebx /* save EBX */
|
|
||||||
pushl %edx /* stack pointer as arg for align_stack */
|
|
||||||
call 1f
|
|
||||||
1: popl %ebx /* address of label 1 */
|
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */
|
|
||||||
call align_stack@PLT /* align stack */
|
|
||||||
movl %eax, %edx /* begin of aligned stack */
|
|
||||||
popl %eax /* remove arg for align_stack */
|
|
||||||
popl %ebx /* restore EBX */
|
|
||||||
popl %eax /* restore pointer to fcontext_t */
|
|
||||||
|
|
||||||
leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */
|
|
||||||
movl %edx, 0x10(%eax) /* save the aligned stack base */
|
|
||||||
|
|
||||||
stmxcsr 0x20(%eax) /* save MMX control and status word */
|
|
||||||
fnstcw 0x24(%eax) /* save x87 control word */
|
|
||||||
|
|
||||||
call 2f
|
|
||||||
2: popl %ecx /* address of label 2 */
|
|
||||||
addl $finish-2b, %ecx /* helper code executed after context function returns */
|
|
||||||
movl %ecx, (%edx)
|
|
||||||
|
|
||||||
xorl %eax, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
leal -0xc(%esp), %esp
|
|
||||||
|
|
||||||
call 3f
|
|
||||||
3: popl %ebx /* address of label 3 */
|
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */
|
|
||||||
|
|
||||||
xorl %eax, %eax
|
|
||||||
pushl %eax /* exit code is zero */
|
|
||||||
call _exit@PLT /* exit application */
|
|
||||||
hlt
|
|
||||||
.size make_fcontext,.-make_fcontext
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/********************************************************************
|
|
||||||
* *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | EDI | ESI | EBX | EBP | ESP | EIP | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 6 | 7 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x18 | 0x1c | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | sbase | slimit | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 8 | 9 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | 0x20 | 0x24 | | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* | fc_mxcsr|fc_x87_cw| | *
|
|
||||||
* -------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _jump_fcontext
|
|
||||||
.align 2
|
|
||||||
_jump_fcontext:
|
|
||||||
movl 0x4(%esp), %ecx /* load address of the first fcontext_t arg */
|
|
||||||
movl %edi, (%ecx) /* save EDI */
|
|
||||||
movl %esi, 0x4(%ecx) /* save ESI */
|
|
||||||
movl %ebx, 0x8(%ecx) /* save EBX */
|
|
||||||
movl %ebp, 0xc(%ecx) /* save EBP */
|
|
||||||
|
|
||||||
leal 0x4(%esp), %eax /* exclude the return address */
|
|
||||||
movl %eax, 0x10(%ecx) /* save as stack pointer */
|
|
||||||
movl (%esp), %eax /* load return address */
|
|
||||||
movl %eax, 0x14(%ecx) /* save return address */
|
|
||||||
|
|
||||||
movl 0x8(%esp), %edx /* load address of the second fcontext_t arg */
|
|
||||||
movl (%edx), %edi /* restore EDI */
|
|
||||||
movl 0x4(%edx), %esi /* restore ESI */
|
|
||||||
movl 0x8(%edx), %ebx /* restore EBX */
|
|
||||||
movl 0xc(%edx), %ebp /* restore EBP */
|
|
||||||
|
|
||||||
movl 0x10(%esp), %eax /* check if fpu enve preserving was requested */
|
|
||||||
test %eax, %eax
|
|
||||||
je 1f
|
|
||||||
|
|
||||||
stmxcsr 0x20(%ecx) /* save MMX control and status word */
|
|
||||||
fnstcw 0x24(%ecx) /* save x87 control word */
|
|
||||||
ldmxcsr 0x20(%edx) /* restore MMX control and status word */
|
|
||||||
fldcw 0x24(%edx) /* restore x87 control word */
|
|
||||||
1:
|
|
||||||
movl 0xc(%esp), %eax /* use third arg as return value after jump */
|
|
||||||
|
|
||||||
movl 0x10(%edx), %esp /* restore ESP */
|
|
||||||
movl %eax, 0x4(%esp) /* use third arg as first arg in context function */
|
|
||||||
movl 0x14(%edx), %edx /* fetch the address to return to */
|
|
||||||
|
|
||||||
jmp *%edx /* indirect jump to context */
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _make_fcontext
|
|
||||||
.align 2
|
|
||||||
_make_fcontext:
|
|
||||||
movl 0x4(%esp), %eax /* load address of the fcontext_t */
|
|
||||||
movl %eax, (%eax) /* save the address of current context */
|
|
||||||
movl 0x8(%esp), %ecx /* load the address of the context function */
|
|
||||||
movl %ecx, 0x14(%eax) /* save the address of the context function */
|
|
||||||
movl 0x18(%eax), %edx /* load the stack base */
|
|
||||||
|
|
||||||
pushl %eax /* save pointer to fcontext_t */
|
|
||||||
pushl %ebx /* save EBX */
|
|
||||||
pushl %edx /* stack pointer as arg for align_stack */
|
|
||||||
call 1f
|
|
||||||
1: popl %ebx /* address of label 1 */
|
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx /* compute address of GOT and store it in EBX */
|
|
||||||
call align_stack@PLT /* align stack */
|
|
||||||
movl %eax, %edx /* begin of aligned stack */
|
|
||||||
popl %eax /* remove arg for align_stack */
|
|
||||||
popl %ebx /* restore EBX */
|
|
||||||
popl %eax /* restore pointer to fcontext_t */
|
|
||||||
|
|
||||||
leal -0x14(%edx), %edx /* reserve space for the last frame on stack, (ESP + 4) % 16 == 0 */
|
|
||||||
movl %edx, 0x10(%eax) /* save the aligned stack base */
|
|
||||||
|
|
||||||
stmxcsr 0x20(%eax) /* save MMX control and status word */
|
|
||||||
fnstcw 0x24(%eax) /* save x87 control word */
|
|
||||||
|
|
||||||
call 2f
|
|
||||||
2: popl %ecx /* address of label 2 */
|
|
||||||
addl $finish-2b, %ecx /* helper code executed after context function returns */
|
|
||||||
movl %ecx, (%edx)
|
|
||||||
|
|
||||||
xorl %eax, %eax
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
leal -0xc(%esp), %esp
|
|
||||||
|
|
||||||
call 3f
|
|
||||||
3: popl %ebx /* address of label 3 */
|
|
||||||
addl $_GLOBAL_OFFSET_TABLE_+[.-3b], %ebx /* compute address of GOT and store it in EBX */
|
|
||||||
|
|
||||||
xorl %eax, %eax
|
|
||||||
pushl %eax /* exit code is zero */
|
|
||||||
call _exit@PLT /* exit application */
|
|
||||||
hlt
|
|
||||||
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
* *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | S0 | S1 | S2 | S3 | S4 | S5 | S6 | S7 | GP | SP | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 10 | 11 | 12 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 80 | 88 | 96 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | S8 | RA | PC | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 13 | 14 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 104 | 112 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* |sbase|slimt| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 15 | 16 | 17 | 18 | 19 | 20 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 120 | 128 | 136 | 144 | 152 | 160 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F20 | F22 | F24 | F26 | F28 | F30 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl jump_fcontext
|
|
||||||
.align 2
|
|
||||||
.type jump_fcontext,@function
|
|
||||||
.ent jump_fcontext
|
|
||||||
jump_fcontext:
|
|
||||||
sw $s0, ($a0) # save S0
|
|
||||||
sw $s1, 8($a0) # save S1
|
|
||||||
sw $s2, 16($a0) # save S2
|
|
||||||
sw $s3, 24($a0) # save S3
|
|
||||||
sw $s4, 32($a0) # save S4
|
|
||||||
sw $s5, 40($a0) # save S5
|
|
||||||
sw $s6, 48($a0) # save S6
|
|
||||||
sw $s7, 56($a0) # save S7
|
|
||||||
sw $gp, 64($a0) # save GP
|
|
||||||
sw $sp, 72($a0) # save SP
|
|
||||||
sw $s8, 80($a0) # save S8
|
|
||||||
sw $ra, 88($a0) # save RA
|
|
||||||
sw $ra, 96($a0) # save RA as PC
|
|
||||||
|
|
||||||
#if defined(__mips_hard_float)
|
|
||||||
beqz $a3, 1f # test if fpu env should be preserved
|
|
||||||
s.d $f20, 120($a0) # save F20
|
|
||||||
s.d $f22, 128($a0) # save F22
|
|
||||||
s.d $f24, 136($a0) # save F24
|
|
||||||
s.d $f26, 144($a0) # save F26
|
|
||||||
s.d $f28, 152($a0) # save F28
|
|
||||||
s.d $f30, 160($a0) # save F30
|
|
||||||
|
|
||||||
l.d $f20, 120($a1) # restore F20
|
|
||||||
l.d $f22, 128($a1) # restore F22
|
|
||||||
l.d $f24, 136($a1) # restore F24
|
|
||||||
l.d $f26, 144($a1) # restore F26
|
|
||||||
l.d $f28, 152($a1) # restore F28
|
|
||||||
l.d $f30, 160($a1) # restore F30
|
|
||||||
1:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lw $s0, ($a1) # restore S0
|
|
||||||
lw $s1, 8($a1) # restore S1
|
|
||||||
lw $s2, 16($a1) # restore S2
|
|
||||||
lw $s3, 24($a1) # restore S3
|
|
||||||
lw $s4, 32($a1) # restore S4
|
|
||||||
lw $s5, 40($a1) # restore S5
|
|
||||||
lw $s6, 48($a1) # restore S6
|
|
||||||
lw $s7, 56($a1) # restore S7
|
|
||||||
lw $gp, 64($a1) # restore GP
|
|
||||||
lw $sp, 72($a1) # restore SP
|
|
||||||
lw $s8, 80($a1) # restore S8
|
|
||||||
lw $ra, 88($a1) # restore RA
|
|
||||||
move $a0, $s2 # restore void pointer as argument
|
|
||||||
|
|
||||||
move $v0, $a2 # use third arg as return value after jump
|
|
||||||
move $a0, $a2 # use third arg as first arg in context function
|
|
||||||
|
|
||||||
lw $t9, 96($a1) # load PC
|
|
||||||
jr $t9 # jump to context
|
|
||||||
.end jump_fcontext
|
|
||||||
.size jump_fcontext, .-jump_fcontext
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl make_fcontext
|
|
||||||
.align 2
|
|
||||||
.type make_fcontext,@function
|
|
||||||
.ent make_fcontext
|
|
||||||
make_fcontext:
|
|
||||||
#ifdef __PIC__
|
|
||||||
.set noreorder
|
|
||||||
.cpload $t9
|
|
||||||
.set reorder
|
|
||||||
#endif
|
|
||||||
sw $a0, ($a0) # save the current context
|
|
||||||
sw $gp, 24($a0) # save global pointer
|
|
||||||
sw $a1, 96($a0) # save the address of the context function
|
|
||||||
lw $t0, 104($a0) # load the stack base
|
|
||||||
|
|
||||||
sub $sp, $sp, 28
|
|
||||||
sw $ra, 24($sp)
|
|
||||||
sw $a0, 20($sp)
|
|
||||||
move $a0, $t0 # stack pointer as arg for align_stack
|
|
||||||
lw $t9, %call16(align_stack)($gp) # align stack
|
|
||||||
jalr $t9
|
|
||||||
nop
|
|
||||||
move $t0, $v0 # begin of aligned stack
|
|
||||||
lw $ra, 24($sp)
|
|
||||||
lw $a0, 20($sp)
|
|
||||||
addi $sp, $sp, 28
|
|
||||||
|
|
||||||
sub $t0, $t0, 16 # reserve 16 byte of argument space
|
|
||||||
sw $t0, 72($a0) # save the algned stack base
|
|
||||||
|
|
||||||
la $t9, finish # helper code executed after context function returns
|
|
||||||
sw $t9, 88($a0)
|
|
||||||
|
|
||||||
move $v0, $zero
|
|
||||||
jr $ra
|
|
||||||
|
|
||||||
finish:
|
|
||||||
move $gp, $s3 # restore GP (global pointer)
|
|
||||||
move $a0, $zero # exit code is zero
|
|
||||||
lw $t9, %call16(_exit)($gp) # exit application
|
|
||||||
jalr $t9
|
|
||||||
.end make_fcontext
|
|
||||||
.size make_fcontext, .-make_fcontext
|
|
||||||
|
|
@ -1,222 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
* *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R13 | R14 | R15 | R16 | R17 | R18 | R19 | R20 | R21 | R22 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R23 | R24 | R25 | R26 | R27 | R28 | R29 | R30 | R31 | SP | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 20 | 21 | 22 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 80 | 84 | 88 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | CR | LR | PC | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 23 | 24 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 92 | 96 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* |sbase|slimt| | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 100 | 104 | 108 | 112 | 116 | 120 | 124 | 128 | 132 | 136 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F14 | F15 | F16 | F17 | F18 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 140 | 144 | 148 | 152 | 156 | 160 | 164 | 168 | 172 | 176 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F19 | F20 | F21 | F22 | F23 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 208 | 212 | 216 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F24 | F25 | F26 | F27 | F28 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 220 | 224 | 228 | 232 | 236 | 240 | 244 | 248 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F29 | F30 | F31 | fpscr | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl jump_fcontext
|
|
||||||
.align 2
|
|
||||||
.type jump_fcontext,@function
|
|
||||||
jump_fcontext:
|
|
||||||
stw %r13, 0(%r3) # save R13
|
|
||||||
stw %r14, 4(%r3) # save R14
|
|
||||||
stw %r15, 8(%r3) # save R15
|
|
||||||
stw %r16, 12(%r3) # save R16
|
|
||||||
stw %r17, 16(%r3) # save R17
|
|
||||||
stw %r18, 20(%r3) # save R18
|
|
||||||
stw %r19, 24(%r3) # save R19
|
|
||||||
stw %r20, 28(%r3) # save R20
|
|
||||||
stw %r21, 32(%r3) # save R21
|
|
||||||
stw %r22, 36(%r3) # save R22
|
|
||||||
stw %r23, 40(%r3) # save R23
|
|
||||||
stw %r24, 44(%r3) # save R24
|
|
||||||
stw %r25, 48(%r3) # save R25
|
|
||||||
stw %r26, 52(%r3) # save R26
|
|
||||||
stw %r27, 56(%r3) # save R27
|
|
||||||
stw %r28, 60(%r3) # save R28
|
|
||||||
stw %r29, 64(%r3) # save R29
|
|
||||||
stw %r30, 68(%r3) # save R30
|
|
||||||
stw %r31, 72(%r3) # save R31
|
|
||||||
stw %r1, 76(%r3) # save SP
|
|
||||||
|
|
||||||
mfcr %r0 # load CR
|
|
||||||
stw %r0, 80(%r3) # save CR
|
|
||||||
mflr %r0 # load LR
|
|
||||||
stw %r0, 84(%r3) # save LR
|
|
||||||
stw %r0, 88(%r3) # save LR as PC
|
|
||||||
|
|
||||||
cmpwi cr7, %r6, 0 # test if fpu env should be preserved
|
|
||||||
beq cr7, 1f
|
|
||||||
|
|
||||||
stfd %f14, 100(%r3) # save F14
|
|
||||||
stfd %f15, 108(%r3) # save F15
|
|
||||||
stfd %f16, 116(%r3) # save F16
|
|
||||||
stfd %f17, 124(%r3) # save F17
|
|
||||||
stfd %f18, 132(%r3) # save F18
|
|
||||||
stfd %f19, 140(%r3) # save F19
|
|
||||||
stfd %f20, 148(%r3) # save F20
|
|
||||||
stfd %f21, 156(%r3) # save F21
|
|
||||||
stfd %f22, 164(%r3) # save F22
|
|
||||||
stfd %f23, 172(%r3) # save F23
|
|
||||||
stfd %f24, 180(%r3) # save F24
|
|
||||||
stfd %f25, 188(%r3) # save F25
|
|
||||||
stfd %f26, 196(%r3) # save F26
|
|
||||||
stfd %f27, 204(%r3) # save F27
|
|
||||||
stfd %f28, 212(%r3) # save F28
|
|
||||||
stfd %f29, 220(%r3) # save F29
|
|
||||||
stfd %f30, 228(%r3) # save F30
|
|
||||||
stfd %f31, 236(%r3) # save F31
|
|
||||||
mffs %f0 # load FPSCR
|
|
||||||
stfd %f0, 244(%r3) # save FPSCR
|
|
||||||
|
|
||||||
lfd %f14, 100(%r4) # restore F14
|
|
||||||
lfd %f15, 108(%r4) # restore F15
|
|
||||||
lfd %f16, 116(%r4) # restore F16
|
|
||||||
lfd %f17, 124(%r4) # restore F17
|
|
||||||
lfd %f18, 132(%r4) # restore F18
|
|
||||||
lfd %f19, 140(%r4) # restore F19
|
|
||||||
lfd %f20, 148(%r4) # restore F20
|
|
||||||
lfd %f21, 156(%r4) # restore F21
|
|
||||||
lfd %f22, 164(%r4) # restore F22
|
|
||||||
lfd %f23, 172(%r4) # restore F23
|
|
||||||
lfd %f24, 180(%r4) # restore F24
|
|
||||||
lfd %f25, 188(%r4) # restore F25
|
|
||||||
lfd %f26, 196(%r4) # restore F26
|
|
||||||
lfd %f27, 204(%r4) # restore F27
|
|
||||||
lfd %f28, 212(%r4) # restore F28
|
|
||||||
lfd %f29, 220(%r4) # restore F29
|
|
||||||
lfd %f30, 228(%r4) # restore F30
|
|
||||||
lfd %f31, 236(%r4) # restore F31
|
|
||||||
lfd %f0, 244(%r4) # load FPSCR
|
|
||||||
mtfsf 0xff, %f0 # restore FPSCR
|
|
||||||
1:
|
|
||||||
|
|
||||||
lwz %r13, 0(%r4) # restore R13
|
|
||||||
lwz %r14, 4(%r4) # restore R14
|
|
||||||
lwz %r15, 8(%r4) # restore R15
|
|
||||||
lwz %r16, 12(%r4) # restore R16
|
|
||||||
lwz %r17, 16(%r4) # restore R17
|
|
||||||
lwz %r18, 20(%r4) # restore R18
|
|
||||||
lwz %r19, 24(%r4) # restore R19
|
|
||||||
lwz %r20, 28(%r4) # restore R20
|
|
||||||
lwz %r21, 32(%r4) # restore R21
|
|
||||||
lwz %r22, 36(%r4) # restore R22
|
|
||||||
lwz %r23, 40(%r4) # restore R23
|
|
||||||
lwz %r24, 44(%r4) # restore R24
|
|
||||||
lwz %r25, 48(%r4) # restore R25
|
|
||||||
lwz %r26, 52(%r4) # restore R26
|
|
||||||
lwz %r27, 56(%r4) # restore R27
|
|
||||||
lwz %r28, 60(%r4) # restore R28
|
|
||||||
lwz %r29, 64(%r4) # restore R29
|
|
||||||
lwz %r30, 68(%r4) # restore R30
|
|
||||||
lwz %r31, 72(%r4) # restore R31
|
|
||||||
lwz %r1, 76(%r4) # restore SP
|
|
||||||
|
|
||||||
lwz %r0, 80(%r4) # load CR
|
|
||||||
mtcr %r0 # restore CR
|
|
||||||
lwz %r0, 84(%r4) # load LR
|
|
||||||
mtlr %r0 # restore LR
|
|
||||||
|
|
||||||
mr. %r3, %r5 # use third arg as return value after jump
|
|
||||||
# and as first arg in context function
|
|
||||||
|
|
||||||
lwz %r0, 88(%r4) # load PC
|
|
||||||
mtctr %r0 # restore CTR
|
|
||||||
|
|
||||||
bctr # jump to context
|
|
||||||
.size jump_fcontext, .-jump_fcontext
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl make_fcontext
|
|
||||||
.align 2
|
|
||||||
.type make_fcontext,@function
|
|
||||||
make_fcontext:
|
|
||||||
stw %r3, 0(%r3) # save the current context
|
|
||||||
stw %r4, 88(%r3) # save the address of the context function
|
|
||||||
lwz %r0, 92(%r3) # load the stack base
|
|
||||||
|
|
||||||
li %r4, 28
|
|
||||||
subf %r1, %r4, %r1 # reserve space on stack
|
|
||||||
stw %r3, 24(%r1) # store pointer to fcontext_t on stack
|
|
||||||
mflr %r4 # load LR
|
|
||||||
stw %r4, 20(%r1) # store LR on stack
|
|
||||||
mr. %r3, %r0 # context stack as arg to align_stack
|
|
||||||
bl align_stack@plt # call align_stack
|
|
||||||
mr. %r0, %r3 # load result into R0
|
|
||||||
lwz %r4, 20(%r1) # pop LR from stack
|
|
||||||
mtlr %r4 # restore LR
|
|
||||||
lwz %r3, 24(%r1) # pop pointer to fcontext_t from stack
|
|
||||||
addi %r1, %r1, 28 # release space on stack
|
|
||||||
|
|
||||||
li %r4, 32
|
|
||||||
subf %r0, %r4, %r0 # 32 bytes on stack for parameter area(== 8 registers)
|
|
||||||
stw %r0, 76(%r3) # save the aligned stack base
|
|
||||||
|
|
||||||
mflr %r0 # load LR
|
|
||||||
bl 1f # jump to label 1
|
|
||||||
1:
|
|
||||||
mflr %r4 # load LR
|
|
||||||
addi %r4, %r4, finish - 1b # address of finish; called after context function returns
|
|
||||||
mtlr %r0 # restore LR
|
|
||||||
stw %r4, 84(%r3)
|
|
||||||
|
|
||||||
li %r3, 0
|
|
||||||
blr
|
|
||||||
|
|
||||||
finish:
|
|
||||||
li %r3, 0 # exit code is zero
|
|
||||||
bl _exit@plt # exit application
|
|
||||||
.size make_fcontext, .-make_fcontext
|
|
||||||
|
|
@ -1,250 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*******************************************************************
|
|
||||||
* *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 0 | 4 | 8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R13 | R14 | R15 | R16 | R17 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R18 | R19 | R20 | R21 | R22 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 80 | 84 | 88 | 92 | 96 | 100 | 104 | 108 | 112 | 116 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R23 | R24 | R25 | R26 | R27 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 120 | 124 | 128 | 132 | 136 | 140 | 144 | 148 | 152 | 156 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | R28 | R29 | R30 | R31 | SP | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 40 | 41 | 42 | 43 | 44 | 45 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 160 | 164 | 168 | 172 | 176 | 180 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | CR | LR | PC | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 46 | 47 | 48 | 49 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 184 | 188 | 192 | 196 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | sbase | slimt | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 200 | 204 | 208 | 212 | 216 | 220 | 224 | 228 | 232 | 236 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F14 | F15 | F16 | F17 | F18 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 240 | 244 | 248 | 252 | 256 | 260 | 264 | 268 | 272 | 276 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F19 | F20 | F21 | F22 | F23 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 280 | 284 | 288 | 292 | 296 | 300 | 304 | 308 | 312 | 316 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F24 | F25 | F26 | F27 | F28 | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | 320 | 324 | 328 | 332 | 336 | 340 | 344 | 348 | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* | F29 | F30 | F31 | fpscr | | *
|
|
||||||
* ------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* *****************************************************************/
|
|
||||||
|
|
||||||
.section ".text"
|
|
||||||
.align 2
|
|
||||||
.globl jump_fcontext
|
|
||||||
.section ".opd","aw"
|
|
||||||
.align 3
|
|
||||||
jump_fcontext:
|
|
||||||
.quad .jump_fcontext,.TOC.@tocbase,0
|
|
||||||
.previous
|
|
||||||
.size jump_fcontext,24
|
|
||||||
.type .jump_fcontext,@function
|
|
||||||
.globl .jump_fcontext
|
|
||||||
.jump_fcontext:
|
|
||||||
std %r13, 0(%r3) # save R13
|
|
||||||
std %r14, 8(%r3) # save R14
|
|
||||||
std %r15, 16(%r3) # save R15
|
|
||||||
std %r16, 24(%r3) # save R16
|
|
||||||
std %r17, 32(%r3) # save R17
|
|
||||||
std %r18, 40(%r3) # save R18
|
|
||||||
std %r19, 48(%r3) # save R19
|
|
||||||
std %r20, 56(%r3) # save R20
|
|
||||||
std %r21, 64(%r3) # save R21
|
|
||||||
std %r22, 72(%r3) # save R22
|
|
||||||
std %r23, 80(%r3) # save R23
|
|
||||||
std %r24, 88(%r3) # save R24
|
|
||||||
std %r25, 96(%r3) # save R25
|
|
||||||
std %r26, 104(%r3) # save R26
|
|
||||||
std %r27, 112(%r3) # save R27
|
|
||||||
std %r28, 120(%r3) # save R28
|
|
||||||
std %r29, 128(%r3) # save R29
|
|
||||||
std %r30, 136(%r3) # save R30
|
|
||||||
std %r31, 144(%r3) # save R31
|
|
||||||
std %r1, 152(%r3) # save SP
|
|
||||||
|
|
||||||
mfcr %r0 # load CR
|
|
||||||
std %r0, 160(%r3) # save CR
|
|
||||||
mflr %r0 # load LR
|
|
||||||
std %r0, 168(%r3) # save LR
|
|
||||||
std %r0, 176(%r3) # save LR as PC
|
|
||||||
|
|
||||||
cmpwi cr7, %r6, 0 # test if fpu env should be preserved
|
|
||||||
beq cr7, 1f
|
|
||||||
|
|
||||||
stfd %f14, 200(%r3) # save F14
|
|
||||||
stfd %f15, 208(%r3) # save F15
|
|
||||||
stfd %f16, 216(%r3) # save F16
|
|
||||||
stfd %f17, 224(%r3) # save F17
|
|
||||||
stfd %f18, 232(%r3) # save F18
|
|
||||||
stfd %f19, 240(%r3) # save F19
|
|
||||||
stfd %f20, 248(%r3) # save F20
|
|
||||||
stfd %f21, 256(%r3) # save F21
|
|
||||||
stfd %f22, 264(%r3) # save F22
|
|
||||||
stfd %f23, 272(%r3) # save F23
|
|
||||||
stfd %f24, 280(%r3) # save F24
|
|
||||||
stfd %f25, 288(%r3) # save F25
|
|
||||||
stfd %f26, 296(%r3) # save F26
|
|
||||||
stfd %f27, 304(%r3) # save F27
|
|
||||||
stfd %f28, 312(%r3) # save F28
|
|
||||||
stfd %f29, 320(%r3) # save F29
|
|
||||||
stfd %f30, 328(%r3) # save F30
|
|
||||||
stfd %f31, 336(%r3) # save F31
|
|
||||||
mffs %f0 # load FPSCR
|
|
||||||
stfd %f0, 344(%r3) # save FPSCR
|
|
||||||
|
|
||||||
lfd %f14, 200(%r4) # restore F14
|
|
||||||
lfd %f15, 208(%r4) # restore F15
|
|
||||||
lfd %f16, 216(%r4) # restore F16
|
|
||||||
lfd %f17, 224(%r4) # restore F17
|
|
||||||
lfd %f18, 232(%r4) # restore F18
|
|
||||||
lfd %f19, 240(%r4) # restore F19
|
|
||||||
lfd %f20, 248(%r4) # restore F20
|
|
||||||
lfd %f21, 256(%r4) # restore F21
|
|
||||||
lfd %f22, 264(%r4) # restore F22
|
|
||||||
lfd %f23, 272(%r4) # restore F23
|
|
||||||
lfd %f24, 280(%r4) # restore F24
|
|
||||||
lfd %f25, 288(%r4) # restore F25
|
|
||||||
lfd %f26, 296(%r4) # restore F26
|
|
||||||
lfd %f27, 304(%r4) # restore F27
|
|
||||||
lfd %f28, 312(%r4) # restore F28
|
|
||||||
lfd %f29, 320(%r4) # restore F29
|
|
||||||
lfd %f30, 328(%r4) # restore F30
|
|
||||||
lfd %f31, 336(%r4) # restore F31
|
|
||||||
lfd %f0, 344(%r4) # load FPSCR
|
|
||||||
mtfsf 0xff, %f0 # restore FPSCR
|
|
||||||
1:
|
|
||||||
|
|
||||||
ld %r13, 0(%r4) # restore R13
|
|
||||||
ld %r14, 8(%r4) # restore R14
|
|
||||||
ld %r15, 16(%r4) # restore R15
|
|
||||||
ld %r16, 24(%r4) # restore R16
|
|
||||||
ld %r17, 32(%r4) # restore R17
|
|
||||||
ld %r18, 40(%r4) # restore R18
|
|
||||||
ld %r19, 48(%r4) # restore R19
|
|
||||||
ld %r20, 56(%r4) # restore R20
|
|
||||||
ld %r21, 64(%r4) # restore R21
|
|
||||||
ld %r22, 72(%r4) # restore R22
|
|
||||||
ld %r23, 80(%r4) # restore R23
|
|
||||||
ld %r24, 88(%r4) # restore R24
|
|
||||||
ld %r25, 96(%r4) # restore R25
|
|
||||||
ld %r26, 104(%r4) # restore R26
|
|
||||||
ld %r27, 112(%r4) # restore R27
|
|
||||||
ld %r28, 120(%r4) # restore R28
|
|
||||||
ld %r29, 128(%r4) # restore R29
|
|
||||||
ld %r30, 136(%r4) # restore r30
|
|
||||||
ld %r31, 144(%r4) # restore r31
|
|
||||||
ld %r1, 152(%r4) # restore SP
|
|
||||||
|
|
||||||
ld %r0, 160(%r4) # load CR
|
|
||||||
mtcr %r0 # restore CR
|
|
||||||
ld %r0, 168(%r4) # load LR
|
|
||||||
mtlr %r0 # restore LR
|
|
||||||
|
|
||||||
mr. %r3, %r5 # use third arg as return value after jump
|
|
||||||
# and as first arg in context function
|
|
||||||
|
|
||||||
ld %r0, 176(%r4) # load PC
|
|
||||||
mtctr %r0 # restore CTR
|
|
||||||
|
|
||||||
bctr # jump to context
|
|
||||||
.size .jump_fcontext, .-.jump_fcontext
|
|
||||||
|
|
||||||
.section ".text"
|
|
||||||
.align 2
|
|
||||||
.globl make_fcontext
|
|
||||||
.section ".opd","aw"
|
|
||||||
.align 3
|
|
||||||
make_fcontext:
|
|
||||||
.quad .make_fcontext,.TOC.@tocbase,0
|
|
||||||
.previous
|
|
||||||
.size make_fcontext,24
|
|
||||||
.type .make_fcontext,@function
|
|
||||||
.globl .make_fcontext
|
|
||||||
.make_fcontext:
|
|
||||||
std %r3, 0(%r3) # save the current context
|
|
||||||
std %r4, 176(%r3) # save the address of the function supposed to be run
|
|
||||||
ld %r0, 184(%r3) # load the stack base
|
|
||||||
|
|
||||||
li %r4, 56
|
|
||||||
subf %r1, %r4, %r1 # reserve space on stack
|
|
||||||
stw %r3, 48(%r1) # store pointer to fcontext_t on stack
|
|
||||||
mflr %r4 # load LR
|
|
||||||
stw %r4, 40(%r1) # store LR on stack
|
|
||||||
mr. %r3, %r0 # context stack as arg to align_stack
|
|
||||||
bl align_stack@plt # call align_stack
|
|
||||||
mr. %r0, %r3 # load result into R0
|
|
||||||
lwz %r4, 40(%r1) # pop LR from stack
|
|
||||||
mtlr %r4 # restore LR
|
|
||||||
lwz %r3, 48(%r1) # pop pointer to fcontext_t from stack
|
|
||||||
addi %r1, %r1, 56 # release space on stack
|
|
||||||
|
|
||||||
li %r4, 64
|
|
||||||
subf %r0, %r4, %r0 # 64 bytes on stack for parameter area (== 8 registers)
|
|
||||||
std %r0, 152(%r3) # save the stack base
|
|
||||||
|
|
||||||
mflr %r0 # load LR
|
|
||||||
bl 1f # jump to label 1
|
|
||||||
1:
|
|
||||||
mflr %r4 # load LR
|
|
||||||
addi %r4, %r4, finish - 1b # calulate absolute address of finish
|
|
||||||
mtlr %r0 # restore LR
|
|
||||||
std %r4, 168(%r3) # save address of finish
|
|
||||||
|
|
||||||
li %r3, 0 # set return value to zero
|
|
||||||
blr
|
|
||||||
|
|
||||||
finish:
|
|
||||||
li %r3, 0 # set return value to zero
|
|
||||||
bl _exit@plt # exit application
|
|
||||||
.size .make_fcontext, .-.make_fcontext
|
|
||||||
|
|
@ -1,207 +0,0 @@
|
||||||
|
|
||||||
; Copyright Oliver Kowalke 2009.
|
|
||||||
; Distributed under the Boost Software License, Version 1.0.
|
|
||||||
; (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
; http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | R12 | R13 | R14 | R15 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | RDI | RSI | RBX | RBP |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 16 | 17 | 18 | 19 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x40 | 0x44 | 0x48 | 0x4c | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | RSP | RIP | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 20 | 21 | 22 | 23 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x50 | 0x54 | 0x58 | 0x5c | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | sbase | slimit | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 24 | 25 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x60 | 0x64 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | fbr_strg | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 26 | 27 | 28 | 29 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x68 | 0x6c | 0x70 | 0x74 | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | fc_mxcsr|fc_x87_cw| fc_xmm | |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x78 | 0x7c | 0x80 | 0x84 | 0x88 | 0x8c | 0x90 | 0x94 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | XMM6 | XMM7 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x98 | 0x9c | 0x100 | 0x104 | 0x108 | 0x10c | 0x110 | 0x114 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | XMM8 | XMM9 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x118 | 0x11c | 0x120 | 0x124 | 0x128 | 0x12c | 0x130 | 0x134 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | XMM10 | XMM11 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x138 | 0x13c | 0x140 | 0x144 | 0x148 | 0x14c | 0x150 | 0x154 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | XMM12 | XMM13 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | 0x158 | 0x15c | 0x160 | 0x164 | 0x168 | 0x16c | 0x170 | 0x174 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
; | XMM14 | XMM15 |
|
|
||||||
; ----------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
EXTERN _exit:PROC ; standard C library function
|
|
||||||
EXTERN align_stack:PROC ; stack alignment
|
|
||||||
EXTERN seh_fcontext:PROC ; exception handler
|
|
||||||
.code
|
|
||||||
|
|
||||||
jump_fcontext PROC EXPORT FRAME:seh_fcontext
|
|
||||||
.endprolog
|
|
||||||
|
|
||||||
mov [rcx], r12 ; save R12
|
|
||||||
mov [rcx+08h], r13 ; save R13
|
|
||||||
mov [rcx+010h], r14 ; save R14
|
|
||||||
mov [rcx+018h], r15 ; save R15
|
|
||||||
mov [rcx+020h], rdi ; save RDI
|
|
||||||
mov [rcx+028h], rsi ; save RSI
|
|
||||||
mov [rcx+030h], rbx ; save RBX
|
|
||||||
mov [rcx+038h], rbp ; save RBP
|
|
||||||
|
|
||||||
mov r10, gs:[030h] ; load NT_TIB
|
|
||||||
mov rax, [r10+08h] ; load current stack base
|
|
||||||
mov [rcx+050h], rax ; save current stack base
|
|
||||||
mov rax, [r10+010h] ; load current stack limit
|
|
||||||
mov [rcx+058h], rax ; save current stack limit
|
|
||||||
mov rax, [r10+018h] ; load fiber local storage
|
|
||||||
mov [rcx+060h], rax ; save fiber local storage
|
|
||||||
|
|
||||||
test r9, r9
|
|
||||||
je nxt
|
|
||||||
|
|
||||||
stmxcsr [rcx+068h] ; save MMX control and status word
|
|
||||||
fnstcw [rcx+06ch] ; save x87 control word
|
|
||||||
mov r10, [rcx+070h] ; address of aligned XMM storage
|
|
||||||
movaps [r10], xmm6
|
|
||||||
movaps [r10+010h], xmm7
|
|
||||||
movaps [r10+020h], xmm8
|
|
||||||
movaps [r10+030h], xmm9
|
|
||||||
movaps [r10+040h], xmm10
|
|
||||||
movaps [r10+050h], xmm11
|
|
||||||
movaps [r10+060h], xmm12
|
|
||||||
movaps [r10+070h], xmm13
|
|
||||||
movaps [r10+080h], xmm14
|
|
||||||
movaps [r10+090h], xmm15
|
|
||||||
|
|
||||||
ldmxcsr [rdx+068h] ; restore MMX control and status word
|
|
||||||
fldcw [rdx+06ch] ; restore x87 control word
|
|
||||||
mov r10, [rdx+070h] ; address of aligned XMM storage
|
|
||||||
movaps xmm6, [r10]
|
|
||||||
movaps xmm7, [r10+010h]
|
|
||||||
movaps xmm8, [r10+020h]
|
|
||||||
movaps xmm9, [r10+030h]
|
|
||||||
movaps xmm10, [r10+040h]
|
|
||||||
movaps xmm11, [r10+050h]
|
|
||||||
movaps xmm12, [r10+060h]
|
|
||||||
movaps xmm13, [r10+070h]
|
|
||||||
movaps xmm14, [r10+080h]
|
|
||||||
movaps xmm15, [r10+090h]
|
|
||||||
nxt:
|
|
||||||
|
|
||||||
lea rax, [rsp+08h] ; exclude the return address
|
|
||||||
mov [rcx+040h], rax ; save as stack pointer
|
|
||||||
mov rax, [rsp] ; load return address
|
|
||||||
mov [rcx+048h], rax ; save return address
|
|
||||||
|
|
||||||
mov r12, [rdx] ; restore R12
|
|
||||||
mov r13, [rdx+08h] ; restore R13
|
|
||||||
mov r14, [rdx+010h] ; restore R14
|
|
||||||
mov r15, [rdx+018h] ; restore R15
|
|
||||||
mov rdi, [rdx+020h] ; restore RDI
|
|
||||||
mov rsi, [rdx+028h] ; restore RSI
|
|
||||||
mov rbx, [rdx+030h] ; restore RBX
|
|
||||||
mov rbp, [rdx+038h] ; restore RBP
|
|
||||||
|
|
||||||
mov r10, gs:[030h] ; load NT_TIB
|
|
||||||
mov rax, [rdx+050h] ; load stack base
|
|
||||||
mov [r10+08h], rax ; restore stack base
|
|
||||||
mov rax, [rdx+058h] ; load stack limit
|
|
||||||
mov [r10+010h], rax ; restore stack limit
|
|
||||||
mov rax, [rdx+060h] ; load fiber local storage
|
|
||||||
mov [r10+018h], rax ; restore fiber local storage
|
|
||||||
|
|
||||||
mov rsp, [rdx+040h] ; restore RSP
|
|
||||||
mov r10, [rdx+048h] ; fetch the address to returned to
|
|
||||||
|
|
||||||
mov rax, r8 ; use third arg as return value after jump
|
|
||||||
mov rcx, r8 ; use third arg as first arg in context function
|
|
||||||
|
|
||||||
jmp r10 ; indirect jump to caller
|
|
||||||
jump_fcontext ENDP
|
|
||||||
|
|
||||||
make_fcontext PROC EXPORT FRAME ; generate function table entry in .pdata and unwind information in E
|
|
||||||
.endprolog ; .xdata for a function's structured exception handling unwind behavior
|
|
||||||
|
|
||||||
mov [rcx], rcx ; store the address of current context
|
|
||||||
mov [rcx+048h], rdx ; save the address of the function supposed to run
|
|
||||||
mov rdx, [rcx+050h] ; load the address where the context stack beginns
|
|
||||||
|
|
||||||
push rcx ; save pointer to fcontext_t
|
|
||||||
sub rsp, 028h ; reserve shadow space for align_stack
|
|
||||||
mov rcx, rdx ; stack pointer as arg for align_stack
|
|
||||||
mov [rsp+8], rcx
|
|
||||||
call align_stack ; align stack
|
|
||||||
mov rdx, rax ; begin of aligned stack
|
|
||||||
add rsp, 028h
|
|
||||||
pop rcx ; restore pointer to fcontext_t
|
|
||||||
|
|
||||||
lea rdx, [rdx-028h] ; reserve 32byte shadow space + return address on stack, (RSP + 8) % 16 == 0
|
|
||||||
mov [rcx+040h], rdx ; save the address where the context stack beginns
|
|
||||||
|
|
||||||
stmxcsr [rcx+068h] ; save MMX control and status word
|
|
||||||
fnstcw [rcx+06ch] ; save x87 control word
|
|
||||||
|
|
||||||
lea rax, finish ; helper code executed after fn() returns
|
|
||||||
mov [rdx], rax ; store address off the helper function as return address
|
|
||||||
|
|
||||||
xor rax, rax ; set RAX to zero
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
xor rcx, rcx
|
|
||||||
mov [rsp+08h], rcx
|
|
||||||
call _exit ; exit application
|
|
||||||
hlt
|
|
||||||
make_fcontext ENDP
|
|
||||||
END
|
|
||||||
|
|
@ -1,116 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/****************************************************************************************
|
|
||||||
* *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | RBX | R12 | R13 | R14 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | R15 | RBP | RSP | RIP | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 16 | 17 | 18 | 19 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | sbase | slimit | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 20 | 21 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x50 | 0x54 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | fc_mxcsr|fc_x87_cw| | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* **************************************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl jump_fcontext
|
|
||||||
.type jump_fcontext,@function
|
|
||||||
.align 16
|
|
||||||
jump_fcontext:
|
|
||||||
movq %rbx, (%rdi) /* save RBX */
|
|
||||||
movq %r12, 0x8(%rdi) /* save R12 */
|
|
||||||
movq %r13, 0x10(%rdi) /* save R13 */
|
|
||||||
movq %r14, 0x18(%rdi) /* save R14 */
|
|
||||||
movq %r15, 0x20(%rdi) /* save R15 */
|
|
||||||
movq %rbp, 0x28(%rdi) /* save RBP */
|
|
||||||
|
|
||||||
cmp $0, %rcx
|
|
||||||
je 1f
|
|
||||||
|
|
||||||
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
|
||||||
fnstcw 0x54(%rdi) /* save x87 control word */
|
|
||||||
|
|
||||||
ldmxcsr 0x50(%rsi) /* restore MMX control and status word */
|
|
||||||
fldcw 0x54(%rsi) /* restore x87 control word */
|
|
||||||
1:
|
|
||||||
|
|
||||||
leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */
|
|
||||||
movq %rax, 0x30(%rdi) /* save as stack pointer */
|
|
||||||
movq (%rsp), %rax /* save return address */
|
|
||||||
movq %rax, 0x38(%rdi) /* save return address as RIP */
|
|
||||||
|
|
||||||
movq (%rsi), %rbx /* restore RBX */
|
|
||||||
movq 0x8(%rsi), %r12 /* restore R12 */
|
|
||||||
movq 0x10(%rsi), %r13 /* restore R13 */
|
|
||||||
movq 0x18(%rsi), %r14 /* restore R14 */
|
|
||||||
movq 0x20(%rsi), %r15 /* restore R15 */
|
|
||||||
movq 0x28(%rsi), %rbp /* restore RBP */
|
|
||||||
|
|
||||||
movq 0x30(%rsi), %rsp /* restore RSP */
|
|
||||||
movq 0x38(%rsi), %rcx /* fetch the address to return to */
|
|
||||||
|
|
||||||
movq %rdx, %rax /* use third arg as return value after jump */
|
|
||||||
movq %rdx, %rdi /* use third arg as first arg in context function */
|
|
||||||
|
|
||||||
jmp *%rcx /* indirect jump to context */
|
|
||||||
.size jump_fcontext,.-jump_fcontext
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl make_fcontext
|
|
||||||
.type make_fcontext,@function
|
|
||||||
.align 16
|
|
||||||
make_fcontext:
|
|
||||||
movq %rdi, (%rdi) /* save the address of passed context */
|
|
||||||
movq %rsi, 0x38(%rdi) /* save the address of the context function */
|
|
||||||
movq 0x40(%rdi), %rdx /* load the stack base */
|
|
||||||
|
|
||||||
pushq %rdi /* save pointer to fcontext_t */
|
|
||||||
movq %rdx, %rdi /* stack pointer as arg for align_stack */
|
|
||||||
call align_stack@PLT /* align stack */
|
|
||||||
movq %rax, %rdx /* begin of aligned stack */
|
|
||||||
popq %rdi /* restore pointer to fcontext_t */
|
|
||||||
|
|
||||||
leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) & 15 == 0 */
|
|
||||||
movq %rdx, 0x30(%rdi) /* save the algined stack base */
|
|
||||||
|
|
||||||
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
|
||||||
fnstcw 0x54(%rdi) /* save x87 control word */
|
|
||||||
|
|
||||||
leaq finish(%rip), %rcx /* address of finish; called after context function returns */
|
|
||||||
movq %rcx, (%rdx)
|
|
||||||
|
|
||||||
xorq %rax, %rax
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
xorq %rdi, %rdi /* exit code is zero */
|
|
||||||
call _exit@PLT /* exit application */
|
|
||||||
hlt
|
|
||||||
.size make_fcontext,.-make_fcontext
|
|
||||||
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright Oliver Kowalke 2009.
|
|
||||||
Distributed under the Boost Software License, Version 1.0.
|
|
||||||
(See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/****************************************************************************************
|
|
||||||
* *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x0 | 0x4 | 0x8 | 0xc | 0x10 | 0x14 | 0x18 | 0x1c | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | RBX | R12 | R13 | R14 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x20 | 0x24 | 0x28 | 0x2c | 0x30 | 0x34 | 0x38 | 0x3c | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | R15 | RBP | RSP | RIP | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 16 | 17 | 18 | 19 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x40 | 0x44 | 0x48 | 0x4c | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | sbase | slimit | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 20 | 21 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | 0x50 | 0x54 | | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* | fc_mxcsr|fc_x87_cw| | *
|
|
||||||
* ---------------------------------------------------------------------------------- *
|
|
||||||
* *
|
|
||||||
* **************************************************************************************/
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _jump_fcontext
|
|
||||||
.align 8
|
|
||||||
_jump_fcontext:
|
|
||||||
movq %rbx, (%rdi) /* save RBX */
|
|
||||||
movq %r12, 0x8(%rdi) /* save R12 */
|
|
||||||
movq %r13, 0x10(%rdi) /* save R13 */
|
|
||||||
movq %r14, 0x18(%rdi) /* save R14 */
|
|
||||||
movq %r15, 0x20(%rdi) /* save R15 */
|
|
||||||
movq %rbp, 0x28(%rdi) /* save RBP */
|
|
||||||
|
|
||||||
cmp $0, %rcx
|
|
||||||
je 1f
|
|
||||||
|
|
||||||
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
|
||||||
fnstcw 0x54(%rdi) /* save x87 control word */
|
|
||||||
|
|
||||||
ldmxcsr 0x50(%rsi) /* restore MMX control and status word */
|
|
||||||
fldcw 0x54(%rsi) /* restore x87 control word */
|
|
||||||
1:
|
|
||||||
|
|
||||||
leaq 0x8(%rsp), %rax /* exclude the return address and save as stack pointer */
|
|
||||||
movq %rax, 0x30(%rdi) /* save as stack pointer */
|
|
||||||
movq (%rsp), %rax /* save return address */
|
|
||||||
movq %rax, 0x38(%rdi) /* save return address as RIP */
|
|
||||||
|
|
||||||
movq (%rsi), %rbx /* restore RBX */
|
|
||||||
movq 0x8(%rsi), %r12 /* restore R12 */
|
|
||||||
movq 0x10(%rsi), %r13 /* restore R13 */
|
|
||||||
movq 0x18(%rsi), %r14 /* restore R14 */
|
|
||||||
movq 0x20(%rsi), %r15 /* restore R15 */
|
|
||||||
movq 0x28(%rsi), %rbp /* restore RBP */
|
|
||||||
|
|
||||||
movq 0x30(%rsi), %rsp /* restore RSP */
|
|
||||||
movq 0x38(%rsi), %rcx /* fetch the address to return to */
|
|
||||||
|
|
||||||
movq %rdx, %rax /* use third arg as return value after jump */
|
|
||||||
movq %rdx, %rdi /* use third arg as first arg in context function */
|
|
||||||
|
|
||||||
jmp *%rcx /* indirect jump to context */
|
|
||||||
|
|
||||||
.text
|
|
||||||
.globl _make_fcontext
|
|
||||||
.align 8
|
|
||||||
_make_fcontext:
|
|
||||||
movq %rdi, (%rdi) /* save the address of current context */
|
|
||||||
movq %rsi, 0x38(%rdi) /* save the address of the function supposed to run */
|
|
||||||
movq 0x40(%rdi), %rdx /* load the stack base */
|
|
||||||
|
|
||||||
pushq %rdi /* save pointer to fcontext_t */
|
|
||||||
movq %rdx, %rdi /* stack pointer as arg for align_stack */
|
|
||||||
call _align_stack /* align stack */
|
|
||||||
movq %rax, %rdx /* begin of aligned stack */
|
|
||||||
popq %rdi /* restore pointer to fcontext_t */
|
|
||||||
|
|
||||||
leaq -0x8(%rdx), %rdx /* reserve space for the last frame on stack, (RSP + 8) % 16 == 0 */
|
|
||||||
movq %rdx, 0x30(%rdi) /* save the address */
|
|
||||||
|
|
||||||
stmxcsr 0x50(%rdi) /* save MMX control and status word */
|
|
||||||
fnstcw 0x54(%rdi) /* save x87 control word */
|
|
||||||
|
|
||||||
leaq finish(%rip), %rcx /* helper code executed after context function returns */
|
|
||||||
movq %rcx, (%rdx)
|
|
||||||
|
|
||||||
xorq %rax, %rax /* set RAX to zero */
|
|
||||||
ret
|
|
||||||
|
|
||||||
finish:
|
|
||||||
xorq %rdi, %rdi /* exit code is zero */
|
|
||||||
call _exit /* exit application */
|
|
||||||
hlt
|
|
||||||
36
vendor/boost_1.51/libs/context/fcontext.cpp
vendored
36
vendor/boost_1.51/libs/context/fcontext.cpp
vendored
|
|
@ -1,36 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
#include <boost/context/fcontext.hpp>
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_PREFIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace ctx {
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
extern "C" BOOST_CONTEXT_DECL
|
|
||||||
void * BOOST_CONTEXT_CALLDECL align_stack( void * vp)
|
|
||||||
{
|
|
||||||
void * base = vp;
|
|
||||||
if ( 0 != ( ( ( uintptr_t) base) & 15) )
|
|
||||||
base = ( char * ) ( ( ( ( uintptr_t) base) - 15) & ~0x0F);
|
|
||||||
return base;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_SUFFIX
|
|
||||||
#endif
|
|
||||||
83
vendor/boost_1.51/libs/context/seh.cpp
vendored
83
vendor/boost_1.51/libs/context/seh.cpp
vendored
|
|
@ -1,83 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <excpt.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winnt.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
# define SNPRINTF _snprintf
|
|
||||||
#else
|
|
||||||
# define SNPRINTF snprintf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const char * exception_description(
|
|
||||||
_EXCEPTION_RECORD const* record, char * description, size_t len)
|
|
||||||
{
|
|
||||||
const DWORD code = record->ExceptionCode;
|
|
||||||
const ULONG_PTR * info = record->ExceptionInformation;
|
|
||||||
|
|
||||||
switch ( code)
|
|
||||||
{
|
|
||||||
case EXCEPTION_ACCESS_VIOLATION:
|
|
||||||
{
|
|
||||||
const char * accessType = ( info[0]) ? "writing" : "reading";
|
|
||||||
const ULONG_PTR address = info[1];
|
|
||||||
SNPRINTF( description, len, "Access violation %s %p", accessType, reinterpret_cast< void * >( address) );
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
case EXCEPTION_DATATYPE_MISALIGNMENT: return "Datatype misalignment";
|
|
||||||
case EXCEPTION_BREAKPOINT: return "Breakpoint";
|
|
||||||
case EXCEPTION_SINGLE_STEP: return "Single step";
|
|
||||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded";
|
|
||||||
case EXCEPTION_FLT_DENORMAL_OPERAND: return "FPU denormal operand";
|
|
||||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "FPU divide by zero";
|
|
||||||
case EXCEPTION_FLT_INEXACT_RESULT: return "FPU inexact result";
|
|
||||||
case EXCEPTION_FLT_INVALID_OPERATION: return "FPU invalid operation";
|
|
||||||
case EXCEPTION_FLT_OVERFLOW: return "FPU overflow";
|
|
||||||
case EXCEPTION_FLT_STACK_CHECK: return "FPU stack check";
|
|
||||||
case EXCEPTION_FLT_UNDERFLOW: return "FPU underflow";
|
|
||||||
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer divide by zero";
|
|
||||||
case EXCEPTION_INT_OVERFLOW: return "Integer overflow";
|
|
||||||
case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction";
|
|
||||||
case EXCEPTION_IN_PAGE_ERROR: return "In page error";
|
|
||||||
case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal instruction";
|
|
||||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Noncontinuable exception";
|
|
||||||
case EXCEPTION_STACK_OVERFLOW: return "Stack overflow";
|
|
||||||
case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition";
|
|
||||||
case EXCEPTION_GUARD_PAGE: return "Guard page";
|
|
||||||
case EXCEPTION_INVALID_HANDLE: return "Invalid handle";
|
|
||||||
}
|
|
||||||
|
|
||||||
SNPRINTF( description, len, "Unknown (0x%08lX)", code);
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
|
|
||||||
EXCEPTION_DISPOSITION seh_fcontext(
|
|
||||||
struct _EXCEPTION_RECORD * record,
|
|
||||||
void *,
|
|
||||||
struct _CONTEXT *,
|
|
||||||
void *)
|
|
||||||
{
|
|
||||||
char description[255];
|
|
||||||
|
|
||||||
fprintf( stderr, "exception: %s (%08lX)\n",
|
|
||||||
exception_description( record, description, sizeof( description) ),
|
|
||||||
record->ExceptionCode);
|
|
||||||
|
|
||||||
ExitProcess( -1);
|
|
||||||
|
|
||||||
return ExceptionContinueSearch; // never reached
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,85 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
#include <boost/context/stack_allocator.hpp>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/format.hpp>
|
|
||||||
|
|
||||||
#include <boost/context/stack_utils.hpp>
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_PREFIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace ctx {
|
|
||||||
|
|
||||||
void *
|
|
||||||
stack_allocator::allocate( std::size_t size) const
|
|
||||||
{
|
|
||||||
if ( minimum_stacksize() > size)
|
|
||||||
throw std::invalid_argument(
|
|
||||||
boost::str( boost::format("invalid stack size: must be at least %d bytes")
|
|
||||||
% minimum_stacksize() ) );
|
|
||||||
|
|
||||||
if ( ! is_stack_unbound() && ( maximum_stacksize() < size) )
|
|
||||||
throw std::invalid_argument(
|
|
||||||
boost::str( boost::format("invalid stack size: must not be larger than %d bytes")
|
|
||||||
% maximum_stacksize() ) );
|
|
||||||
|
|
||||||
const std::size_t pages( page_count( size) + 1); // add +1 for guard page
|
|
||||||
std::size_t size_ = pages * pagesize();
|
|
||||||
|
|
||||||
|
|
||||||
# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
|
|
||||||
void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
||||||
# else
|
|
||||||
const int fd( ::open("/dev/zero", O_RDONLY) );
|
|
||||||
BOOST_ASSERT( -1 != fd);
|
|
||||||
void * limit = ::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
|
||||||
::close( fd);
|
|
||||||
# endif
|
|
||||||
if ( ! limit) throw std::bad_alloc();
|
|
||||||
|
|
||||||
const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
|
|
||||||
BOOST_ASSERT( 0 == result);
|
|
||||||
(void)result; // unused in release build
|
|
||||||
|
|
||||||
return static_cast< char * >( limit) + size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
stack_allocator::deallocate( void * vp, std::size_t size) const
|
|
||||||
{
|
|
||||||
if ( vp)
|
|
||||||
{
|
|
||||||
const std::size_t pages( page_count( size) + 1); // add +1 for guard page
|
|
||||||
std::size_t size_ = pages * pagesize();
|
|
||||||
BOOST_ASSERT( 0 < size && 0 < size_);
|
|
||||||
void * limit = static_cast< char * >( vp) - size_;
|
|
||||||
::munmap( limit, size_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_SUFFIX
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,86 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
#include <boost/context/stack_allocator.hpp>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <windows.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
#include <boost/cstdint.hpp>
|
|
||||||
#include <boost/format.hpp>
|
|
||||||
|
|
||||||
#include <boost/context/stack_utils.hpp>
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_PREFIX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# if defined(BOOST_MSVC)
|
|
||||||
# pragma warning(push)
|
|
||||||
# pragma warning(disable:4244 4267)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace ctx {
|
|
||||||
|
|
||||||
void *
|
|
||||||
stack_allocator::allocate( std::size_t size) const
|
|
||||||
{
|
|
||||||
if ( minimum_stacksize() > size)
|
|
||||||
throw std::invalid_argument(
|
|
||||||
boost::str( boost::format("invalid stack size: must be at least %d bytes")
|
|
||||||
% minimum_stacksize() ) );
|
|
||||||
|
|
||||||
if ( ! is_stack_unbound() && ( maximum_stacksize() < size) )
|
|
||||||
throw std::invalid_argument(
|
|
||||||
boost::str( boost::format("invalid stack size: must not be larger than %d bytes")
|
|
||||||
% maximum_stacksize() ) );
|
|
||||||
|
|
||||||
const std::size_t pages( page_count( size) + 1); // add +1 for guard page
|
|
||||||
std::size_t size_ = pages * pagesize();
|
|
||||||
|
|
||||||
#ifndef BOOST_CONTEXT_FIBER
|
|
||||||
void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
if ( ! limit) throw std::bad_alloc();
|
|
||||||
|
|
||||||
DWORD old_options;
|
|
||||||
const BOOL result = ::VirtualProtect(
|
|
||||||
limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
|
|
||||||
BOOST_ASSERT( FALSE != result);
|
|
||||||
|
|
||||||
return static_cast< char * >( limit) + size_;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
stack_allocator::deallocate( void * vp, std::size_t size) const
|
|
||||||
{
|
|
||||||
if ( vp)
|
|
||||||
{
|
|
||||||
const std::size_t pages( page_count( size) + 1); // add +1 for guard page
|
|
||||||
std::size_t size_ = pages * pagesize();
|
|
||||||
BOOST_ASSERT( 0 < size && 0 < size_);
|
|
||||||
void * limit = static_cast< char * >( vp) - size_;
|
|
||||||
::VirtualFree( limit, 0, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
# if defined(BOOST_MSVC)
|
|
||||||
# pragma warning(pop)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
#ifdef BOOST_HAS_ABI_HEADERS
|
|
||||||
# include BOOST_ABI_SUFFIX
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
#include <boost/context/stack_utils.hpp>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <signal.h>
|
|
||||||
#include <sys/resource.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
static rlimit stacksize_limit_()
|
|
||||||
{
|
|
||||||
rlimit limit;
|
|
||||||
const int result = ::getrlimit( RLIMIT_STACK, & limit);
|
|
||||||
BOOST_ASSERT( 0 == result);
|
|
||||||
(void)result; // unused when in release mode...
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static rlimit stacksize_limit()
|
|
||||||
{
|
|
||||||
static rlimit limit = stacksize_limit_();
|
|
||||||
return limit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace ctx {
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t default_stacksize()
|
|
||||||
{
|
|
||||||
static std::size_t size = 256 * 1024;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t minimum_stacksize()
|
|
||||||
{ return SIGSTKSZ; }
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t maximum_stacksize()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT( ! is_stack_unbound() );
|
|
||||||
return static_cast< std::size_t >( stacksize_limit().rlim_max);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
bool is_stack_unbound()
|
|
||||||
{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t pagesize()
|
|
||||||
{
|
|
||||||
static std::size_t pagesize( ::getpagesize() );
|
|
||||||
return pagesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t page_count( std::size_t stacksize)
|
|
||||||
{
|
|
||||||
return static_cast< std::size_t >(
|
|
||||||
std::ceil(
|
|
||||||
static_cast< float >( stacksize) / pagesize() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
|
|
||||||
// Copyright Oliver Kowalke 2009.
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt)
|
|
||||||
|
|
||||||
#define BOOST_CONTEXT_SOURCE
|
|
||||||
|
|
||||||
#include <boost/context/stack_utils.hpp>
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
#include <windows.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <csignal>
|
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
static SYSTEM_INFO system_info_()
|
|
||||||
{
|
|
||||||
SYSTEM_INFO si;
|
|
||||||
::GetSystemInfo( & si);
|
|
||||||
return si;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SYSTEM_INFO system_info()
|
|
||||||
{
|
|
||||||
static SYSTEM_INFO si = system_info_();
|
|
||||||
return si;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
namespace ctx {
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t default_stacksize()
|
|
||||||
{
|
|
||||||
static std::size_t size = 256 * 1024;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t minimum_stacksize()
|
|
||||||
{
|
|
||||||
static std::size_t stacksize(
|
|
||||||
static_cast< std::size_t >( system_info().dwAllocationGranularity) );
|
|
||||||
return stacksize;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t maximum_stacksize()
|
|
||||||
{
|
|
||||||
BOOST_ASSERT( ! is_stack_unbound() );
|
|
||||||
static std::size_t stacksize = 8 * 1024 * 1024;
|
|
||||||
return stacksize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows seams not to provide a limit for the stacksize
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
bool is_stack_unbound()
|
|
||||||
{ return true; }
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t pagesize()
|
|
||||||
{
|
|
||||||
static std::size_t pagesize(
|
|
||||||
static_cast< std::size_t >( system_info().dwPageSize) );
|
|
||||||
return pagesize;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_CONTEXT_DECL
|
|
||||||
std::size_t page_count( std::size_t stacksize)
|
|
||||||
{
|
|
||||||
return static_cast< std::size_t >(
|
|
||||||
std::ceil(
|
|
||||||
static_cast< float >( stacksize) / pagesize() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
Loading…
Reference in a new issue