Logs: remove mem-mapped buffer and move instance lock to main.cpp

Part of the work to untangle utilities from RPCS3-specific things.
This commit is contained in:
Nekotekina 2020-03-06 21:11:47 +03:00
parent 1669e95870
commit 2209be5216
4 changed files with 54 additions and 82 deletions

View File

@ -1147,7 +1147,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
return;
}
if (mode & fs::trunc && mode & (fs::lock + fs::unread))
if (mode & fs::trunc && mode & (fs::lock + fs::unread) && mode & fs::write)
{
// Postpone truncation in order to avoid using O_TRUNC on a locked file
verify(HERE), ::ftruncate(fd, 0) == 0;

View File

@ -62,17 +62,13 @@ namespace logs
class file_writer
{
fs::file m_file;
std::string m_name;
std::thread m_writer;
fs::file m_fout;
fs::file m_fout2;
u64 m_max_size;
#ifdef _WIN32
::HANDLE m_fmap;
#endif
uchar* m_fptr{};
std::unique_ptr<uchar[]> m_fptr;
z_stream m_zs{};
shared_mutex m_m;
@ -345,61 +341,9 @@ logs::file_writer::file_writer(const std::string& name)
: m_name(name)
{
const std::string log_name = fs::get_cache_dir() + name + ".log";
const std::string buf_name = fs::get_cache_dir() + name + ".buf";
const std::string s_filelock = fs::get_cache_dir() + ".restart_lock";
try
{
if (!m_file.open(buf_name, fs::read + fs::rewrite + fs::lock))
{
#ifdef _WIN32
auto prev_error = fs::g_tls_error;
if (fs::exists(s_filelock))
{
// A restart is happening, wait for the file to be accessible
u32 tries = 0;
while (!m_file.open(buf_name, fs::read + fs::rewrite + fs::lock) && tries < 100)
{
std::this_thread::sleep_for(100ms);
tries++;
}
}
else
{
fs::g_tls_error = prev_error;
}
if (!m_file)
#endif
{
if (fs::g_tls_error == fs::error::acces)
{
if (fs::exists(buf_name))
{
fmt::throw_exception("Another instance of %s is running. Close it or kill its process, if necessary.", name);
}
else
{
fmt::throw_exception("Cannot create %s.log (access denied)."
#ifdef _WIN32
"\nNote that %s cannot be installed in Program Files or similar directory with limited permissions."
#else
"\nPlease, check %s permissions in '~/.config/'."
#endif
, name, name);
}
}
fmt::throw_exception("Cannot create %s.log (error %s)", name, fs::g_tls_error);
}
}
#ifdef _WIN32
fs::remove_file(s_filelock); // remove restart token if it exists
#endif
// Check free space
fs::device_stat stats{};
if (!fs::statfs(fs::get_cache_dir(), stats) || stats.avail_free < s_log_size * 8)
@ -410,16 +354,8 @@ logs::file_writer::file_writer(const std::string& name)
// Limit log size to ~25% of free space
m_max_size = stats.avail_free / 4;
// Initialize memory mapped file
#ifdef _WIN32
m_fmap = CreateFileMappingW(m_file.get_handle(), 0, PAGE_READWRITE, s_log_size >> 32, s_log_size & 0xffffffff, 0);
m_fptr = m_fmap ? static_cast<uchar*>(MapViewOfFile(m_fmap, FILE_MAP_WRITE, 0, 0, 0)) : nullptr;
#else
m_file.trunc(s_log_size);
m_fptr = static_cast<uchar*>(::mmap(0, s_log_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_file.get_handle(), 0));
#endif
verify(name.c_str()), m_fptr;
// Initialize ringbuffer
m_fptr = std::make_unique<uchar[]>(s_log_size);
// Rotate backups (TODO)
if (std::string gz_file_name = fs::get_cache_dir() + m_name + ".log.gz"; fs::is_file(gz_file_name))
@ -533,13 +469,9 @@ logs::file_writer::~file_writer()
FILE_DISPOSITION_INFO disp;
disp.DeleteFileW = false;
SetFileInformationByHandle(m_fout2.get_handle(), FileDispositionInfo, &disp, sizeof(disp));
UnmapViewOfFile(m_fptr);
CloseHandle(m_fmap);
#else
// Restore compressed log file permissions
::fchmod(m_fout2.get_handle(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
::munmap(m_fptr, s_log_size);
#endif
}
@ -556,7 +488,7 @@ bool logs::file_writer::flush(u64 bufv)
const u64 size = std::min<u64>(end - st, sizeof(m_zout) / 2);
// Write uncompressed
if (m_fout && st < m_max_size && m_fout.write(m_fptr + st % s_log_size, size) != size)
if (m_fout && st < m_max_size && m_fout.write(m_fptr.get() + st % s_log_size, size) != size)
{
m_fout.close();
}
@ -565,7 +497,7 @@ bool logs::file_writer::flush(u64 bufv)
if (m_fout2 && st < m_max_size)
{
m_zs.avail_in = static_cast<uInt>(size);
m_zs.next_in = m_fptr + st % s_log_size;
m_zs.next_in = m_fptr.get() + st % s_log_size;
do
{
@ -613,7 +545,7 @@ void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
}
v += size;
return m_fptr + (v1 + v2) % s_log_size;
return m_fptr.get() + (v1 + v2) % s_log_size;
});
if (!pos) [[unlikely]]
@ -631,11 +563,11 @@ void logs::file_writer::log(logs::level sev, const char* text, std::size_t size)
continue;
}
if (pos + size > m_fptr + s_log_size)
if (pos + size > m_fptr.get() + s_log_size)
{
const auto frag = m_fptr + s_log_size - pos;
const auto frag = m_fptr.get() + s_log_size - pos;
std::memcpy(pos, text, frag);
std::memcpy(m_fptr, text + frag, size - frag);
std::memcpy(m_fptr.get(), text + frag, size - frag);
}
else
{

View File

@ -35,6 +35,7 @@ DYNAMIC_IMPORT("ntdll.dll", NtSetTimerResolution, NTSTATUS(ULONG DesiredResoluti
#include "rpcs3_version.h"
#include "Emu/System.h"
#include <thread>
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
@ -203,8 +204,51 @@ QCoreApplication* createApplication(int& argc, char* argv[])
return new gui_application(argc, argv);
}
int main(int argc, char** argv)
{
const std::string lock_name = fs::get_cache_dir() + "RPCS3.buf";
fs::file instance_lock;
for (u32 num = 0; num < 100 && !instance_lock.open(lock_name, fs::rewrite + fs::lock); num++)
{
std::this_thread::sleep_for(30ms);
}
if (!instance_lock)
{
QApplication app0{argc, argv};
s_qt_init.unlock();
if (fs::g_tls_error == fs::error::acces)
{
if (fs::exists(lock_name))
{
report_fatal_error("Another instance of RPCS3 is running. Close it or kill its process, if necessary.");
}
else
{
report_fatal_error("Cannot create RPCS3.log (access denied)."
#ifdef _WIN32
"\nNote that RPCS3 cannot be installed in Program Files or similar directory with limited permissions."
#else
"\nPlease, check RPCS3 permissions in '~/.config/rpcs3'."
#endif
);
}
}
else
{
report_fatal_error(fmt::format("Cannot create RPCS3.log (error %s)", fs::g_tls_error));
}
return 1;
}
logs::set_init();
#ifdef __linux__

View File

@ -561,10 +561,6 @@ bool update_manager::handle_rpcs3(const QByteArray& rpcs3_data, bool /*automatic
replace_path = Emulator::GetEmuDir() + "rpcs3.exe";
// Creating a file to indicate we're restarting
const std::string s_filelock = fs::get_cache_dir() + ".restart_lock";
verify("Restart lock" HERE), !!fs::file(s_filelock, fs::create);
#endif
m_progress_dialog->close();