I have developed an application (application1) that uses boost::log with
severity_channel_logger_mt and two sinks (syslog_backend &
text_file_backend).
When I run the application as an .exe, the sinks work fine and I am able to see log text files generate from messages being passed across a network, but when
I link application1 as a .dll inside of another application (mainapp), I get
the following errors after about 20 seconds:
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: boost::wrapexcept<boost::system::system_error> at memory location 0x000000F9BD9FF220.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: boost::wrapexcept<boost::system::system_error> at memory location 0x000000F9BD9FF220.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: boost::wrapexcept<boost::system::system_error> at memory location 0x000000F9BD9FF220.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: [rethrow] at memory location 0x0000000000000000.
Exception thrown at 0x00007FFA9E03CD29 in mainapp.exe: Microsoft C++ exception: boost::wrapexcept<boost::system::system_error> at memory location 0x000000F9BD9FF220.
After debugging, the exception happens in basic_sink_frontend.hpp and core.hpp between these two calls:
basic_sink_frontend.hpp
backend.consume(rec, context->m_FormattedRecord);
core.hpp
BOOST_FORCEINLINE void push_record(BOOST_RV_REF(record) rec)
{
push_record_move(static_cast< record& >(rec));
}
I have verified that the "rec" variable is not NULL.
The application1 DLL loads wihout error and I am able to run application1 functions from mainapp.
I still see message being passed across network from syslog sink, however text_file sink logs are not generated...
I built boost as a shared library and have the following libs in boost_1_80_0/stage/lib:
boost_log_setup-vc142-mt-x64-1_80
boost_log-vc142-mt-gd-x64-1_80
boost_log-vc142-mt-x64-1_80
Snippets from my code on how I use the loggers and sinks are below. Application1 uses boost::log and MainApp loads Application1 as DLL:
Application1:
#define DEFAULT_PORT 13000
#define DEFAULT_PORT_STRING "13000"
#define DEFAULT_IP "127.0.0.1"
enum class severity_levels
{
info,
warning,
error
};
void Application1::init_builtin_syslog()
{
// Create a syslog sink
boost::shared_ptr< sinks::synchronous_sink< sinks::syslog_backend > > sys_sink(
new sinks::synchronous_sink< sinks::syslog_backend >());
sys_sink->set_formatter
(
expr::stream << "Application 1 Log - ID: " << expr::attr< unsigned int >("RecordID")
<< "| " << expr::attr< severity_levels >("Severity") << ": " << expr::smessage
);
// We'll have to map our custom levels to the syslog levels
sinks::syslog::custom_severity_mapping< severity_levels > mapping("Severity");
mapping[severity_levels::info] = sinks::syslog::info;
mapping[severity_levels::warning] = sinks::syslog::warning;
mapping[severity_levels::error] = sinks::syslog::critical;
sys_sink->locked_backend()->set_severity_mapper(mapping);
#if !defined(BOOST_LOG_NO_ASIO)
// Set the remote address to send syslog messages to
sys_sink->locked_backend()->set_target_address(DEFAULT_IP, DEFAULT_PORT);
#endif
//Create a text file sink
boost::shared_ptr< sinks::synchronous_sink< sinks::text_file_backend > > file_sink(
new sinks::synchronous_sink< sinks::text_file_backend >(
keywords::file_name = "application1.log", // file name pattern
keywords::target_file_name = "application1_%Y%m%d_%H%M%S_%2N.log",
keywords::rotation_size = 16384
));
// Set up where the rotated files will be stored
file_sink->locked_backend()->set_file_collector(sinks::file::make_collector(
keywords::target = "logs",
keywords::max_size = 64 * 1024 * 1024,
keywords::min_free_space = 100 * 1024 * 1024,
keywords::max_files = 512
));
// Upon restart, scan the target directory for files matching the file_name pattern
file_sink->locked_backend()->scan_for_files();
file_sink->set_formatter
(
expr::format("%1% Application 1 Log - ID: %2% | %3% : \"%4%\"")
% expr::attr< boost::posix_time::ptime >("TimeStamp")
% expr::attr< unsigned int >("RecordID")
% expr::attr< severity_levels >("Severity")
% expr::smessage
);
// Add the sinks to the core
logging::core::get()->add_sink(sys_sink);
logging::core::get()->add_sink(file_sink);
// Add logging attributes
logging::core::get()->add_global_attribute("RecordID", attrs::counter< unsigned int >());
logging::core::get()->add_global_attribute("TimeStamp", attrs::utc_clock());
}
int start()
{
init_builtin_syslog();
src::severity_channel_logger_mt\< severity_levels \> lg(keywords::severity = severity_levels::info, keywords::channel = "Application 1");
for (int i = 0; i \< 10000; ++i)
{
BOOST_LOG_SEV(lg, severity_levels::info) \<\< infoLog;
if(runexe) std::cout \<\< "App1 sent: " \<\< infoLog \<\< std::endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
}
return 0;
}
MainApp:
bool loadedApp1 = false;
std::atomic<bool> startApp1 = true;
std::atomic<char*> app1Err((char*)"");
HINSTANCE app1dll;
void printError( const TCHAR* msg );
typedef void (*MYPROC2)(std::atomic<bool>&, std::atomic<char*>&);
MYPROC2 app1start;
int main()
{
std::cout << "Starting application 1... " << std::endl;
try
{
app1dll = LoadLibrary(TEXT("application1.dll"));
if(app1dll == NULL)
{
std::cerr << "Application 1 DLL load library failure." << GetLastError() << '\n';
loadedApp1 = false;
}
else
{
loadedApp1 = true;
app1start = (MYPROC2) GetProcAddress(app1dll, MAKEINTRESOURCEA(1));
if (NULL != app1start)
{
std::thread t1(app1start, std::ref(startApp1), std::ref(app1Err));
t1.detach();
std::this_thread::sleep_for(std::chrono::milliseconds(4000));
}
if(startApp1.load() == false)
{
std::cout << "Error starting Application 1: " << app1Err.load() << std::endl;
}
}
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
return 1;
}
return 0;
}
Related
I have an application that must monitor some folders (in Windows) to detect if a file was created in that folder (real use is to detect incoming FTP files).
If a file is detected , it is read, then deleted .
Occasionally, I get a file reading error on a file that was detected.
Question is: Why?
To simulate the error, I created a simple program to reproduce it:
std::vector<std::filesystem::path> watch;
void main()
{
watch.push_back("D:\\test1"); //must exist
watch.push_back("D:\\test2");
watch_dir();
}
this example monitors 2 folders.
To simulate incoming files on the folder, another program copies files to that folder
continuously at configurable intervals (say 100 milliseconds).
To detect folder changes , WIN32 API functions FindFirstChangeNotification and WaitForMultipleObjects are used, based on this Microsoft example
https://learn.microsoft.com/en-us/windows/win32/fileio/obtaining-directory-change-notifications
detection function adapted from the example (Note: WaitForMultipleObjects blocks until a change is detected)
void watch_dir()
{
HANDLE handle[2];
memset(handle, 0, 2 * sizeof(HANDLE));
for (size_t idx = 0; idx < watch.size(); idx++)
{
std::string str = watch.at(idx).string();
LPTSTR path = (LPTSTR)str.c_str();
std::cout << "watch path " << path << std::endl;
handle[idx] = FindFirstChangeNotification(
path, // directory to watch
FALSE, // do not watch subtree
FILE_NOTIFY_CHANGE_FILE_NAME); // watch file name changes
if (handle[idx] == INVALID_HANDLE_VALUE)
{
assert(0);
ExitProcess(GetLastError());
}
}
while (TRUE)
{
std::cout << "Waiting for notification..." << std::endl;
DWORD wait_status = WaitForMultipleObjects(watch.size(), handle, FALSE, INFINITE);
std::cout << "Directory " << watch.at(wait_status) << " changed" << std::endl;
if (FindNextChangeNotification(handle[wait_status]) == FALSE)
{
assert(0);
ExitProcess(GetLastError());
}
std::filesystem::path path = watch.at(wait_status);
send_files_in_path(path);
}
}
Once a change is detected by the function above, then all files in the folder are listed
and read, by these functions
void send_files_in_path(const std::filesystem::path& ftp_path)
{
std::vector<std::filesystem::path> list = get_files(ftp_path);
for (size_t idx = 0; idx < list.size(); idx++)
{
std::string buf;
read_file(list.at(idx).string(), buf);
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::filesystem::remove(list.at(idx));
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
//get_files
//get all ".txt" files inside a FTP folder
/////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<std::filesystem::path> get_files(const std::filesystem::path& base_archive_path)
{
std::vector<std::filesystem::path> list;
try
{
for (const auto& entry : std::filesystem::recursive_directory_iterator(base_archive_path))
{
std::filesystem::path path = entry.path();
if (!entry.is_regular_file())
{
continue;
}
std::string fname = entry.path().filename().string();
size_t len = fname.size();
size_t pos = len - 4;
//check if last 4 characters are ".txt"
if (fname.find(".txt", pos) == std::string::npos && fname.find(".TXT", pos) == std::string::npos)
{
continue;
}
SPDLOG_INFO("loading: " + entry.path().string());
list.push_back(path);
}//this path
} //try
catch (const std::exception& e)
{
SPDLOG_ERROR(e.what());
}
return list;
}
The function where the error happens is
int read_file(const std::string& fname, std::string& buf)
{
std::ifstream ifs;
std::ios_base::iostate mask = ifs.exceptions() | std::ios::failbit;
ifs.exceptions(mask);
std::this_thread::sleep_for(std::chrono::milliseconds(0));
std::cout << "opening : " << fname << std::endl;
try
{
ifs.open(fname);
if (!ifs.is_open())
{
std::cout << "open fail: " << fname << std::endl;
return -1;
}
}
catch (const std::exception& e)
{
std::cout << e.what() << std::endl;
return -1;
}
std::stringstream ss;
ss << ifs.rdbuf();
ifs.close();
buf = ss.str();
return 0;
}
the try/catch block, again, occasionally , is triggered with the error
ios_base::failbit set: iostream stream error
removing the try/catch block, and the open mask (just to try), then
ifs.is_open
fails.
A temporary solution was to detect the cases where the open() failed and repeat it.. which succeeds, because the file does exist.
Calling this with a small delay before the open call has the effect of reducing the open fails
std::this_thread::sleep_for(std::chrono::milliseconds(10));
ifs.open(fname);
But still would like to find out the reason for the occasional failure
I'm in the process of messing around with GRPC. Currently I'm using a C# web application as my GRPC server and I'm using a C++ console application as the client.
I was able to successfully connect and communicate with the server with no issue. The problem arises when
I exit the C++ console client application. Upon exiting an Access Violation is thrown.
Stack trace
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body
MeterReaderClientCpp.exe!__acrt_lock
ntdll.dll!RtlpWaitOnCriticalSection()
ntdll.dll!RtlpEnterCriticalSectionContended()
ntdll.dll!RtlEnterCriticalSection()
MeterReaderClientCpp.exe!__acrt_lock(__acrt_lock_id _Lock) Line 55
MeterReaderClientCpp.exe!_free_dbg(void * block, int block_use) Line 1019
MeterReaderClientCpp.exe!free(void * block) Line 32
MeterReaderClientCpp.exe!gpr_free(void * p) Line 53
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::destroy_thread() Line 142
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::Join() Line 112
MeterReaderClientCpp.exe!grpc_core::Thread::Join() Line 147
MeterReaderClientCpp.exe!gc_completed_threads() Line 74
MeterReaderClientCpp.exe!stop_threads() Line 331
MeterReaderClientCpp.exe!grpc_timer_manager_set_threading(bool threaded) Line 351
MeterReaderClientCpp.exe!grpc_shutdown_internal_locked() Line 175
MeterReaderClientCpp.exe!grpc_shutdown_internal(void * __formal) Line 208
MeterReaderClientCpp.exe!`anonymous namespace'::ThreadInternalsWindows::thread_body(void * v) Line 128
GRPC Client
int main( )
{
using namespace MeterReaderWeb::Services;
using namespace google::protobuf::util;
using namespace google::protobuf;
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
std::fstream file{ R"(C:\Certificates\certificate.cer)", std::ios::in | std::ios::beg };
if ( !file.is_open( ) )
{
std::cerr << "Failed to open file\n";
return 1;
}
std::stringstream buffer;
buffer << file.rdbuf( );
grpc::SslCredentialsOptions options;
options.pem_root_certs = buffer.str( );
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
ReadingPacket packet;
packet.set_status( ReadingStatus::METER_READER_SUCCESS );
packet.set_notes( "Here are some random notes" );
auto message{ packet.add_readings( ) };
message->set_customer_id( 1 );
message->set_reading_value( 10001 );
auto timestamp{ message->mutable_reading_time( ) };
timestamp->CopyFrom( TimeUtil::GetCurrentTime( ) );
grpc::ClientContext context;
StatusMessage response;
if ( auto status{ stub->AddReading( &context, packet, &response ) }; status.ok( ) )
{
std::cout << "Added reading successfully\n";
auto responseStatus{ response.status( ) };
if ( responseStatus == ReadingStatus::METER_READER_SUCCESS )
{
std::cout << "Server status: success\n"
<< "Message: " << response.message( ) << '\n';
}
}
else
{
std::cerr << "Error: " << status.error_message( ) << '\n';
std::cerr << "Error Details: " << status.error_details( ) << '\n';
}
std::cin.ignore( );
}
I heavily used the GRPC route_guide_client.cc as a guide to help me write the above application.
I've tried adding calls to both grpc_init( ) and grpc_shutdown( ) even though their client examples don't contain either calls. But adding those had no effect.
What (if anything) am I missing here? Did I forget to call/populate something that the framework is attempting to clean up upon application exit?
OK I believe I've found what was causing the issue.
In my original post I said:
I've tried adding calls to both grpc_init( ) and grpc_shutdown( ) even though
the client examples don't contain either calls. But
adding those had no effect."
This was true, but after re-reading the documentation for grpc_shutdown( ) i noticed this (emphasis mine):
The last call to grpc_shutdown will initiate cleaning up of grpc
library internals, which can happen in another thread. Once the
clean-up is done, no memory is used by grpc, nor are any instructions
executing within the grpc library. Prior to calling, all application
owned grpc objects must have been destroyed.
This is where I think I went wrong. I was calling grpc_shutdown() while I still had grpc objects in scope. To correct I scoped the grpc objects and then called grpc_shutdown() once that scope was exited. This seems to have corrected the issue.
New Grpc Client
int main( )
{
std::cout << "Press enter\n";
std::cin.ignore( );
std::cout << "Calling Grpc service\n";
grpc_init( );
{ // <- Intentionally added scope here.
grpc::SslCredentialsOptions options;
if ( auto certificate{ ReadCertificate( ) } )
options.pem_root_certs = std::move( certificate ).value( );
else return 1;
auto credentials{ grpc::SslCredentials( options ) };
auto channel{ grpc::CreateChannel( "localhost:5001", credentials ) };
auto stub{ MeterReadingService::NewStub( channel ) };
std::cout << "Sending single packet\n";
SendPacket( stub.get( ), 8000 );
std::cout << "Sending multiple packets\n";
StreamDiagnostics( stub.get( ), 3 );
}
std::cout << "Shutting down library\n";
grpc_shutdown_blocking( );
std::cout << "Shut down complete press enter to exit\n";
std::cin.ignore( );
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have written an application in c++ with OpenCV and boost and it is running well and correct, but before exiting it crashes (if I debug step by step, it crashes when return 0; at the end of main) saying:
in kdevelop:
*** Error in `/home/xxx/git_repos/my_proj/build/my_proj': free(): invalid pointer: 0x00000000008939c0 ***
*** Crashed with return code: 0 ***
in command line:
*** Error in `./my_proj': free(): invalid pointer: 0x00000000008939c0 ***
Aborted (core dumped)
if I use gdb:
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
*** Error in `/home/xxx/git_repos/my_proj/build/plate_info_extractor': free(): invalid pointer: 0x00000000008939c0 ***
Program received signal SIGABRT, Aborted.
0x00007ffff5b83cc9 in __GI_raise (sig=sig#entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
Any help please? I cannot figure out what is wrong.
I have commented some code parts and it seems that the problem is in the code that I use to log the errors/info... So:
#include "CLogger.hpp"
static void help(const std::string& appNameIn)
{
std::cerr << "Usage: " << appNameIn << " <option(s)> SOURCES" << std::endl
<< "Options:" << std::endl
<< " -h,--help Show this help message" << std::endl
<< " -c,--config CONFIG FILE Specify the name and path to the config file" << std::endl
<< std::endl
<< std::endl;
}
enum RetVals
{
NO_ERRORS,
NOT_ENOUGH_PARAMETERS,
UNKNOWN_OPTION,
SHOW_USAGE,
UNKNOWN_EXCEPTION,
OTHER_EXCEPTION,
};
int main(int argc, char **argv)
{
Logger::initFilesList();
Logger::initLogging();
BoostLogger lg = setClassNameAttribute("main");
if (argc == 3)
{
std::string opt = argv[1];
if (opt == "-c" || opt == "--config")
{
try
{
std::cout << "running" << std::endl;
}
catch (std::exception& e)
{
BOOST_LOG_SEV(lg, Logger::SeverityLevels::error) << "Other exception: " << e.what();
return OTHER_EXCEPTION;
}
catch (...)
{
BOOST_LOG_SEV(lg, Logger::SeverityLevels::error) << "Unkown exception ...";
return UNKNOWN_EXCEPTION;
}
}
else
{
help(argv[0]);
BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "The options are -c or --config, -h or --help";
return UNKNOWN_OPTION;
}
}
else if (argc == 2 && (std::string(argv[1]) == "-h" || std::string(argv[1]) == "--help"))
{
help(argv[0]);
BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "Call help function";
return SHOW_USAGE;
}
else
{
help(argv[0]);
BOOST_LOG_SEV(lg, Logger::SeverityLevels::debug) << "The number of input parameters is wrong";
return NOT_ENOUGH_PARAMETERS;
}
return NO_ERRORS;
}
and the CLogger.hpp:
#pragma once
#include <list>
#include <string>
#include <boost/log/common.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <boost/concept_check.hpp>
#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;
class Logger
{
private:
static std::list< std::string > sm_logFilesList;
static const std::string sm_folderOfLogFiles;
/** the function adds the input log file to the list
*
* #param logFilePathIn : input log file path
*/
static void addNewLogFileToList(const std::string& logFilePathIn, bool sorting = false);
/** The function adds new logs to new log file and remove the oltest ones to have always 2 log files */
static void addNewRemoveOldLogs(bool sorting = false);
/** #returns : if the input path is valid or not */
static bool checkPath(const boost::filesystem::path& pathIn);
/** #returns if the file with the first input path was more recent accesed than the file with the second input path
*/
static bool compareAccessTime(const std::string& path1In, const std::string& path2In);
/** The function remove the old log files and keeps just the most recent two */
static void removeOldLogFiles();
/** The function is calles at the end of each file and removes the old files keeping just the last two */
static void openingHandler(boost::log::sinks::text_file_backend::stream_type& file);
public:
enum SeverityLevels
{
debug,
info,
warning,
error
};
/** The function sets the sm_logFilesList to contain the files if there are log files from earlier runs */
static void initFilesList();
/** The fuction is initializing the sinks and the formatter of the logger */
static void initLogging();
};
typedef boost::log::sources::severity_logger< Logger::SeverityLevels > BoostLogger;
/** the overloaded << operator of the BoostLogger */
std::ostream& operator<< (std::ostream& strm, Logger::SeverityLevels level);
/** The function sets the logger attribute ClassName to the specified string and returns the initialized logger
*
* #param classNameIn : input string name of the class
*
* #returns : initialized BoostLogger
*/
BoostLogger setClassNameAttribute(const std::string& classNameIn);
and the implementation:
#include "CLogger.hpp"
#include <boost/log/attributes.hpp>
#include <boost/log/attributes/current_process_id.hpp>
#include <boost/log/attributes/current_process_name.hpp>
#include <boost/log/core/core.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks/sync_frontend.hpp>
#include <boost/log/sinks/text_file_backend.hpp>
#include <boost/log/sinks/text_ostream_backend.hpp>
#include <boost/log/sources/severity_logger.hpp>
#include <boost/log/support/date_time.hpp>
#include <boost/log/utility/setup/file.hpp>
typedef boost::log::sinks::synchronous_sink< boost::log::sinks::text_file_backend > SinkTextFileBakend;
BOOST_LOG_ATTRIBUTE_KEYWORD(correlid, "CorrelationID", std::string)
BOOST_LOG_ATTRIBUTE_KEYWORD(severity, "Severity", Logger::SeverityLevels)
BOOST_LOG_ATTRIBUTE_KEYWORD(timestamp, "TimeStamp", boost::posix_time::ptime)
BOOST_LOG_ATTRIBUTE_KEYWORD(threadid, "ThreadID", boost::log::attributes::current_thread_id)
BOOST_LOG_ATTRIBUTE_KEYWORD(classname, "ClassName", std::string)
std::list< std::string > Logger::sm_logFilesList;
const std::string Logger::sm_folderOfLogFiles = "../logs/";
std::ostream& operator<<(std::ostream& strm, Logger::SeverityLevels level)
{
static const char* strings[] =
{
"DEBUG",
"INFO",
"WARN",
"ERROR"
};
if (static_cast< std::size_t >(level) < sizeof(strings) / sizeof(*strings))
strm << strings[level];
else
strm << static_cast< int >(level);
return strm;
}
BoostLogger setClassNameAttribute(const std::string& classNameIn)
{
BoostLogger lg;
lg.add_attribute("ClassName", boost::log::attributes::constant<std::string>(classNameIn));
return lg;
}
void Logger::removeOldLogFiles()
{
while (sm_logFilesList.size() > 2)
{
std::string fileToDelete = sm_logFilesList.front();
if (fs::exists(fs::path(fileToDelete)))
{
fs::remove(fs::path(fileToDelete));
sm_logFilesList.pop_front();
}
}
}
bool Logger::compareAccessTime(const std::string& path1In, const std::string& path2In)
{
return (fs::last_write_time(fs::path(path1In)) < fs::last_write_time(fs::path(path2In)));
}
void Logger::addNewLogFileToList(const std::string& logFilePathIn, bool sorting)
{
if (std::find(sm_logFilesList.begin(), sm_logFilesList.end(), logFilePathIn) == sm_logFilesList.end())
{
sm_logFilesList.push_back(logFilePathIn);
if (sorting)
{
sm_logFilesList.sort(compareAccessTime);
}
removeOldLogFiles();
}
}
void Logger::addNewRemoveOldLogs(bool sorting)
{
fs::path path(sm_folderOfLogFiles);
fs::directory_iterator endDir;
if (checkPath(path))
{
for (fs::directory_iterator it(path); it != endDir; it++)
{
if (fs::is_regular_file(it->status()))
{
if (fs::extension(*it) == ".log")
{
std::string fileToPush = it->path().string();
addNewLogFileToList(fileToPush, sorting);
}
}
}
}
}
bool Logger::checkPath(const boost::filesystem::path& pathIn)
{
if (!fs::exists(pathIn))
{
return false;
}
if (!fs::is_directory(pathIn))
{
return false;
}
return true;
}
void Logger::openingHandler(boost::log::sinks::text_file_backend::stream_type& file)
{
addNewRemoveOldLogs();
}
void Logger::initFilesList()
{
addNewRemoveOldLogs(true);
}
void Logger::initLogging()
{
// Create a backend
boost::shared_ptr< SinkTextFileBakend > sink = boost::log::add_file_log(
sm_folderOfLogFiles + "plate_info_extractor_%Y-%m-%d_%H-%M-%S.%N.log",
boost::log::keywords::format = boost::log::expressions::stream
<< boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("Executable") << "("
<< boost::log::expressions::attr< boost::log::attributes::current_process_id::value_type >("ExeUID") << ") CID("
<< correlid << ") " << severity << "["
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
<< "] [" << boost::log::expressions::attr< boost::log::attributes::current_thread_id::value_type >("ThreadID")
<< "] " << classname << " - " << boost::log::expressions::smessage,
boost::log::keywords::open_mode = (std::ios::out | std::ios::app),
boost::log::keywords::rotation_size = 2 * 1024 * 1024,
boost::log::keywords::auto_flush = true
);
sink->locked_backend()->set_open_handler(&openingHandler);
boost::log::core::get()->set_filter(severity >= SeverityLevels::info);
boost::log::core::get()->add_sink(sink);
#ifdef DEBUGGING
boost::shared_ptr< boost::log::sinks::text_ostream_backend > backend =
boost::make_shared< boost::log::sinks::text_ostream_backend >();
backend->add_stream(
boost::shared_ptr< std::ostream >(&std::cout));
// Enable auto-flushing after each log record written
backend->auto_flush(true);
// Wrap it into the frontend and register in the core.
// The backend requires synchronization in the frontend.
// for testing and printing log in sysout
boost::shared_ptr< boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend > > backend_sink(
new boost::log::sinks::synchronous_sink< boost::log::sinks::text_ostream_backend >(backend));
backend_sink->set_formatter(
boost::log::expressions::stream
// line id will be written in hex, 8-digits, zero-filled
<< boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("Executable")
<< "(" << boost::log::expressions::attr< boost::log::attributes::current_process_name::value_type >("ExeUID")
<< ") CID(" << correlid << ") " << severity << " ["
<< boost::log::expressions::format_date_time< boost::posix_time::ptime >("TimeStamp", "%Y-%m-%d %H:%M:%S.%f")
<< "] [" << boost::log::expressions::attr< boost::log::attributes::current_thread_id::value_type >("ThreadID")
<< "] " << classname << " - " << boost::log::expressions::smessage);
boost::log::core::get()->add_sink(backend_sink); // for testing and printing log in sysout
#endif
}
I hope that now there is enough information :)
This line:
backend->add_stream(boost::shared_ptr< std::ostream >(&std::cout));
looks pretty disastrous me. Your program will attempt to delete std::cout when exiting. I'm not familiar with Boost Log, so I don't know how to properly set up a sink for std::cout.
As Arpegius pointed out you should use the null_deleter to avoid deletion. Something along the lines of this:
backend->add_stream(boost::shared_ptr< std::ostream>(&std::cout, boost::null_deleter()));
boost::interprocess::message_queue constructor failing when processes are run under different users.
To be more concrete. I'm creating message_queue in proc1. and trying to open the same message_queue from proc2 (another user).
Is it possible to make it working? Or I should find another way to synchronize my processes?
boost-1.52
OS: Windows 7 x86
Compiler: MSVC 2010
P.S. The code is trivial. And completely working if both processes was started from the same user.
P.P.S. This is a message box I've got. I could not call LastWindowError()...
---------------------------
Error
---------------------------
Runtime Error (at 18:421):
External exception E06D7363.
---------------------------
ОК
---------------------------
My code (of the Process2):
void ipcMsg1(HWND hWnd) {
util::MsgBox mb(hWnd, L"Sending Message1");
try {
mb.info(L"create mq");
bipc::message_queue mq(bipc::open_or_create, plmqproto::g_mqName, plmqproto::g_mqSize, sizeof(int));
mb.info(L"created");
const int msg = plmqproto::g_mqMessage1;
mq.send(&msg, sizeof(msg), 0);
bipc::message_queue::remove(plmqproto::g_mqName);
} catch(const bipc::interprocess_exception &ex) {
mb.error(plcore::stringToWString(ex.what()));
std::wstringstream ss;
const unsigned long we = GetLastError();
ss << L">1. GetLastError: " << we << std::endl;
ss << L" " << plcore::GetWindowsErrorMessage(we);
mb.error(ss.str());
} catch(const std::exception &ex) {
mb.error(plcore::stringToWString(ex.what()));
std::wstringstream ss;
const unsigned long we = GetLastError();
ss << L">2. GetLastError: " << we << std::endl;
ss << L" " << plcore::GetWindowsErrorMessage(we);
mb.error(ss.str());
} catch(...) {
std::wstringstream ss;
const unsigned long we = GetLastError();
ss << L">3. GetLastError: " << we << std::endl;
ss << L" " << plcore::GetWindowsErrorMessage(we);
mb.error(ss.str());
}
}
So. I'm getting only "create mq" message box. and fail after that.
Boost upgrade did not helped.
I trying to use Boost.log library from Andrey Semashev
I have some problem with multithreaded-logging with settings file.
Code of main program:
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
using boost::shared_ptr;
// Here we define our application severity levels.
enum severity_level
{
normal,
notification,
warning,
error,
critical
};
BOOST_LOG_DECLARE_GLOBAL_LOGGER(test_lg, src::severity_logger_mt<>)
void try_logging( std::string c )
{
BOOST_LOG_SCOPED_THREAD_TAG("Tag", std::string, c.c_str());
src::severity_logger_mt<>& lg = get_test_lg();
BOOST_LOG_SEV(lg, normal) << "This is a normal severity record";
BOOST_LOG_SEV(lg, notification) << "This is a notification severity record";
BOOST_LOG_SEV(lg, warning) << "This is a warning severity record";
BOOST_LOG_SEV(lg, error) << "This is a error severity record";
BOOST_LOG_SEV(lg, critical) << "This is a critical severity record";
}
int main(int argc, char* argv[])
{
try
{
// Open the file
std::ifstream settings("settings.txt");
if (!settings.is_open())
{
std::cout << "Could not open settings.txt file" << std::endl;
return 1;
}
// Read the settings and initialize logging library
logging::init_from_stream(settings);
shared_ptr< logging::attribute > attr(new attrs::local_clock);
logging::core::get()->add_global_attribute("TimeStamp", attr);
boost::thread_group g;
for (char i = 'a'; i < 'z'; i++)
g.create_thread(boost::bind(&try_logging, std::string("aaa") + i));
g.join_all();
system("PAUSE");
return 0;
}
catch (std::exception& e)
{
std::cout << "FAILURE: " << e.what() << std::endl;
return 1;
}
}
Settings file:
[Core]
Filter="%Severity% >= 2"
[Sink:2]
Destination=TextFile
FileName=test.log
AutoFlush=true
Format="[%TimeStamp%] %Tag% %_%"
Asynchronous=1
Filter="%Tag% = aaab"
[Sink:3]
Filter="%Tag% = aaaa"
Asynchronous=1
Destination=TextFile
FileName=test.log
AutoFlush=true
Format="%Tag% %_%"
As you see, i setup filtering: i want to output just messages from aaab, aaaa threads.
But result file is very bad:
[2011-Jul-18 11:32:58.078192] aaab This aaaa This is a error severity [2011-Juaaaa This is a critical severity record
r severity record
[2011-Jul-18 11:32:58.437581] aaab This is a critical severity record
One message override other! As I understood - there's no synchronyzing between multiple threads.
If i remove filtering - result is all rigth.
How i can fix it? If it's possible - with config file, not code.
Thank you.