boost.log auto_flush files are not stored when app is crashed - boost

Recently I started to play with boost.log, and bumped into an issue that if an unhanded exception is thrown no log messages are written to the log file. I am using rolling text files and auto-flash option is set on.
Here is the modified source from the samples:
#include <stdexcept>
#include <string>
#include <iostream>
#include <fstream>
#include <functional>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <boost/log/common.hpp>
#include <boost/log/filters.hpp>
#include <boost/log/formatters.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/sinks.hpp>
#include <boost/log/utility/empty_deleter.hpp>
#include <boost/log/utility/record_ordering.hpp>
namespace logging = boost::log;
namespace attrs = boost::log::attributes;
namespace src = boost::log::sources;
namespace sinks = boost::log::sinks;
namespace fmt = boost::log::formatters;
namespace keywords = boost::log::keywords;
using boost::shared_ptr;
using namespace boost::gregorian;
enum
{
LOG_RECORDS_TO_WRITE = 100,
LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION = 10,
THREAD_COUNT = 10
};
BOOST_LOG_DECLARE_GLOBAL_LOGGER(test_lg, src::logger_mt)
//! This function is executed in multiple threads
void thread_fun(boost::barrier& bar)
{
// Wait until all threads are created
bar.wait();
// Here we go. First, identify the thread.
BOOST_LOG_SCOPED_THREAD_TAG("ThreadID", boost::thread::id, boost::this_thread::get_id());
// Now, do some logging
for (unsigned int i = 0; i < LOG_RECORDS_TO_WRITE; ++i)
{
BOOST_LOG(get_test_lg()) << "Log record " << i;
if(i > LOG_RECORDS_TO_WRITE_BEFORE_EXCEPTION)
{
BOOST_THROW_EXCEPTION(std::exception("unhandled exception"));
}
}
}
int main(int argc, char* argv[])
{
try
{
typedef sinks::synchronous_sink< sinks::text_file_backend > file_sink;
shared_ptr< file_sink > sink(new file_sink(
keywords::file_name = L"%Y%m%d_%H%M%S_%5N.log", // file name pattern
keywords::rotation_size = 10 * 1024 * 1024, // rotation size, in characters
keywords::auto_flush = true // make each log record flushed to the file
));
// Set up where the rotated files will be stored
sink->locked_backend()->set_file_collector(sinks::file::make_collector(
keywords::target = "log" // where to store rotated files
));
// Upon restart, scan the target directory for files matching the file_name pattern
sink->locked_backend()->scan_for_files();
sink->locked_backend()->set_formatter(
fmt::format("%1%: [%2%] [%3%] - %4%")
% fmt::attr< unsigned int >("Line #")
% fmt::date_time< boost::posix_time::ptime >("TimeStamp")
% fmt::attr< boost::thread::id >("ThreadID")
% fmt::message()
);
// Add it to the core
logging::core::get()->add_sink(sink);
// Add some attributes too
shared_ptr< logging::attribute > attr(new attrs::local_clock);
logging::core::get()->add_global_attribute("TimeStamp", attr);
attr.reset(new attrs::counter< unsigned int >);
logging::core::get()->add_global_attribute("Line #", attr);
// Create logging threads
boost::barrier bar(THREAD_COUNT);
boost::thread_group threads;
for (unsigned int i = 0; i < THREAD_COUNT; ++i)
threads.create_thread(boost::bind(&thread_fun, boost::ref(bar)));
// Wait until all action ends
threads.join_all();
return 0;
}
catch (std::exception& e)
{
std::cout << "FAILURE: " << e.what() << std::endl;
return 1;
}
}
Source is compiled under Visual Studio 2008. boost.log compiled for boost 1.40.
Any help is highly appreciated.

Check to see if the log file is in the current working directory of the process, rather than the specified file collector target directory ("log" in your sample code). Additionally, you will probably want to specify a directory for the sink "file_name" pattern.
As "JQ" notes, don't expect to see any logging post-exception.

Related

How to drive my credential provider with CredUIPromptForWindowsCredentials

I've been working on a credential provider and I've been debugging it through logging. Recently learned about CredUIPromptForWindowsCredentials() API to be able to invoke it from other than login screen or remote desktop connection. The only way at this time I can seem to get my credential to display is to set the last param to CREDUIWIN_SECURE_PROMPT. I've tried various schemes of the flags with no luck. My CP works, that's not the problem. Problem is easier debugging. Only once have I had to go to rescue mode when I made my laptop unbootable. ;) The problem with using the CREDUIWIN_SECURE_PROMPT flag is that then I don't have access to the debugger because login takes over the screen and I can't get back to my debugger. I suppose the only workaround would be to remote debug on another machine with this API, but I'd prefer not to hassle with that.
My CP is registered at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers\{55157584-ff0f-48ce-9178-a4e290901663} and the default property is "MyCredProvider" (for this example). (GUID, prop name changed to protect the guilty. Also ignore LsaString where bad things would happen on a copy--of which I'm not doing.)
Any way to get my custom CP without using the secure prompt?
#include <windows.h>
#include <iostream>
#include <EvoApi.h>
#include <decrypt.h>
#include <atlbase.h>
#include <Lmwksta.h>
#include <StrSafe.h>
#include <LMAPIbuf.h>
#include <LMJoin.h>
#include <wincred.h>
#include <NTSecAPI.h>
#pragma warning(disable : 4996)
#pragma comment(lib, "netapi32.lib")
#pragma comment(lib, "credui.lib")
#pragma comment(lib, "secur32")
using namespace std;
template <size_t SIZE = 256>
struct LsaString : public LSA_STRING
{
LsaString()
{
MaximumLength = SIZE;
Length = 0;
Buffer = pBuf.get();
}
LsaString(LPCSTR pWhat)
{
MaximumLength = SIZE;
Length = 0;
Buffer = pBuf.get();
Init(pWhat);
}
void Init(LPCSTR pWhat)
{
size_t len = strlen(pWhat);
if (len >= SIZE)
throw;
strcpy(Buffer, pWhat);
Length = (USHORT) len;
}
unique_ptr<char[]> pBuf = make_unique< char[] >(SIZE);
};
int _tmain(int argc, wchar_t* argv[])
{
#if 1
wstring me(_T("MYLOGING"));
wstring url(_T("Header"));
wstring message(_T("Enter credentials for ..."));
CREDUI_INFOW credInfo;
credInfo.pszCaptionText = url.c_str();
credInfo.hbmBanner = nullptr;
credInfo.hwndParent = NULL;
credInfo.pszMessageText = message.c_str();
credInfo.cbSize = sizeof(CREDUI_INFOW);
ULONG authPackage = 0;
LSAHANDLE lsaHandle;
LsaConnectUntrusted(&lsaHandle);
LsaString<> lsaString("MyCredProvider");
//LsaString<> lsaString(MICROSOFT_KERBEROS_NAME_A); // works ... as far as finding in LsaLookupAuth...
//LsaString<> lsaString(NEGOSSP_NAME_A); // works ... as far as finding in LsaLookupAuth...
ULONG ulPackage = 0;
LsaLookupAuthenticationPackage(lsaHandle, &lsaString, &ulPackage);
void* pBlob;
ULONG blobSize = 0;
DWORD dwFlags = CREDUIWIN_GENERIC; //CREDUIWIN_SECURE_PROMPT
CredUIPromptForWindowsCredentials(&credInfo, 0, &ulPackage, NULL, 0, &pBlob, &blobSize, FALSE, dwFlags);
if (pBlob) CoTaskMemFree(pBlob);
return 0;
}

How do i pass a variable as wchat_t** from a std::wstring in c++

I am using VS 2019 and the C++ Language Standard is set to Default which I assume is C++ 11?
I have the following constructor of a class in a header file:
input_parser(int& argc, wchar_t** argv)
{
for (auto i = 0; i < argc; ++i)
{
this->tokens_.emplace_back(argv[i]);
}
};
To call the methods argv parameter I am creating an array of wchar_t in the following manner:
std::wstring command_line = L"-m \"F-14RHV\" -s \"BIT|Flir\" -d";
auto buffer = new wchar_t[command_line.length() + 1];
wcsncpy_s(buffer, command_line.length()+1, command_line.c_str(), command_line.length() + 1);
const auto inputs = input_parser(argc, &buffer);
delete[] buffer;
Inside the constructor the first pass when argc == 0 is fine but I get an access violation when argc == 1.
Okay so some programmer dude was correct and here is how I have to do it after I figure out how to split the string by spaces!
Here is the final answer:
#include <string>
#include <sstream>
#include <algorithm>
#include <iostream>
#include <iterator>
std::wstring text = L"-m \"F-14RHV\" -s \"BIT|Flir\" -d";
std::wistringstream iss(text);
std::vector<std::wstring> results((std::istream_iterator<std::wstring, wchar_t>(iss)),
std::istream_iterator<std::wstring, wchar_t>());
Using a vector is going to make this process MUCH easier. I will probably change the other side to use a vector now.
Thanks for the help.

boost filesystem making long path under windows using \\?\

it is so simple but i can not make it work and i do not know why??
i just want to make directory with long path.
i add \\\\?\\ to E:\\... to make it as win api says .
but in vain.....nothing but error.
i tried \\?\ and \?\ with no success.
this is the code :
// boost_create_directory.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <fstream>
#include <string>
#include <time.h>
#include <stdio.h>
#include <ctime>
#include <iostream>
#include <map> //Needed to use the std::map class.
//#include "symbols_array2.h"
//#include "functions.h"
#include <boost/filesystem.hpp>
//#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
////#include <filesystem>
////namespace fs = std::filesystem;
//#define DOWNLOAD_ALL true
int main()
{
using namespace std;
using namespace boost::filesystem;
//string localpath, binlocalfile, localfile;
string localpath = "\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\";
//boost::filesystem::path abs_localpath;
////string localpath = "E:\\instruments\\symbol\\year\\month\\day\\";
boost::filesystem::path abs_localpath(localpath) ;
////string localpath = "\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\";
////boost::filesystem::path abs_localpath("\\\\?\\E:\\instruments\\symbol\\year\\month\\day\\");
////string localpath = "E:/i/";
////boost::filesystem::path abs_localpath("\\?\E:\instruments\symbol\year\month\day\\");
////boost::filesystem::path path_argument(localpath);
////boost::filesystem::path path_native(path_argument.make_preferred());
////boost::filesystem::path abs_localpath(absolute(path_native));
//binlocalfile = localpath + "\\hourh_ticks.bin";
//localfile = localpath + "\\hourh_ticks.bi5";
//abs_localpath = boost::filesystem::absolute(localpath.c_str());
//abs_localpath = localpath;
//if (!boost::filesystem::exists(abs_localpath))
//{
//boost::filesystem::path abs_localpath;
//cout << current_path().string() << endl;
//cout << abs_localpath << endl;
//boost::filesystem::create_directory(abs_localpath);
for (int z = 0; z < 10; z++)
{
if (boost::filesystem::create_directory(abs_localpath)) {
std::cout << "Success making new directory" << "\n";
//boost::filesystem::permissions(abs_localpath, perms_mask);
}
//localpath = localpath + "\\instruments\\symbol\\year\\month\\day";
abs_localpath / "instruments\\symbol\\year\\month\\day\\";
////abs_localpath /= "\instruments\symbol\year\month\day\";
}
//mkdir($localpath, 0777, true);
//}
boost::filesystem::path path("\\?\\E:\\MyStuff\\");
boost::filesystem::create_directory(path);
return 0;
}
i hope to find answer here.thanks in advance.
it was my fault .the create_directory function make single directory if path is already created and return with error if path is missing,So i needed create_directories the plural version make all missing elements of path and voila.
i wish they change these names to create_single_directory or create_target_directory and change the plural to create_path_directories

Compilation issue with boost range copy of filesystem path

The following code fails to compile with 1.58 while it was compiling with 1.46. I guess it's a type conversion issue, but I can't make it right.
my code
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <vector>
using namespace boost;
using namespace filesystem;
using namespace adaptors;
int main(int argc, char ** argv)
{
recursive_directory_iterator beg = recursive_directory_iterator(".");
recursive_directory_iterator end = recursive_directory_iterator();
iterator_range<recursive_directory_iterator> files =
make_iterator_range(beg, end);
std::function<bool (path const & path)> fileFilter =
[](path const & path) -> bool {
return is_regular_file(path);
};
std::vector<path> paths;
copy(files | filtered(fileFilter), std::back_inserter(paths));
// works:
//copy(files, std::back_inserter(paths));
// also works:
//for(recursive_directory_iterator it = beg; it != end; ++it){
// if(fileFilter(*it)){
// paths.push_back(*it);
// }
//}
}
Error message (VS2010)
Error 1 error C2664:
'boost::filesystem::recursive_directory_iterator::recursive_directory_iterator(const
boost::filesystem::path
&,boost::filesystem::symlink_option::enum_type)' : cannot convert
parameter 1 from
'boost::iterators::detail::postfix_increment_proxy' to
'const boost::filesystem::path
&' [...]\boost\1.58.0_32\include\boost-1_58\boost\range\concepts.hpp 201 1 [...]
Can anyone help ?
Edit
Filed as https://svn.boost.org/trac/boost/ticket/11228.
This seems to be a bug introduced somewhere since Boost 1.55. Using boost 1.55 this compiles ok.
It could be this bug: https://svn.boost.org/trac/boost/ticket/10989
boost_1_57_0/boost/concept_check.hpp|210 col 13| error: conversion from ‘boost::iterators::single_pass_traversal_tag’ to non-scalar type ‘boost::iterators::forward_traversal_tag’ requested
The filtered adaptor requires the input to be forward_traversal tag. But recursive_directory_iterator only promises single_pass_traversal tag:
BOOST_RANGE_CONCEPT_ASSERT((
Convertible<
BOOST_DEDUCED_TYPENAME ForwardIteratorConcept::traversal_category,
forward_traversal_tag
>));
WORKAROUND
You can disable concept checks for now: -DBOOST_RANGE_ENABLE_CONCEPT_ASSERT=0:
Live On Coliru
#include <boost/filesystem.hpp>
#include <boost/range.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <vector>
#include <iostream>
namespace fs = boost::filesystem;
using namespace boost::adaptors;
int main() {
fs::recursive_directory_iterator beg("."), end;
auto fileFilter = [](fs::path const & path) { return is_regular_file(path); };
std::vector<fs::path> paths;
copy(boost::make_iterator_range(beg, end) | filtered(fileFilter), std::back_inserter(paths));
for(auto& p : paths)
std::cout << p << "\n";
}
Prints
"./main.cpp"
"./a.out"

Why won't this program work in release mode?

#include <iostream>
#include <fstream>
#include <stdlib.h> // includes the "atoi" function
#include <string>
using namespace std;
#include <sstream>;
int main()
{
std::fstream f;
f.open("file.in", std::fstream::in);
// read data
int count = 0;
std::string line = "";
getline( f, line, '\n' );
count = atoi( line.c_str() );
f.close();
f.open("file.in", std::fstream::out | std::fstream::trunc);
// write data
++count;
f << count << endl;
f.close();
return 0;
}
This works in debug mode in Visual Studio but when I run it as an application it doesn't work. I've initialized all variables so I'm not sure what else to check.
This line
f.open("file.in", std::fstream::in);
Make sure file.in is in \bin\release
I also advice your to use try/catch statements and print your errors

Resources