I'm having a strange issue that I think I have a workaround for, but I'm trying to do a root cause analysis on.
I've been developing an application that runs on an embedded version of Ubuntu 10.04 LTS. When the application starts up, it reads in a config file off of an SD card, initializes a few classes, starts a logger which writes to the SD card, and then proceeds with it's operation. During development, it has been running fine when I start it manually through an SSH terminal.
I've recently been experimenting with having the application start automatically when the OS starts up. I have a script in init.d which does just that. However, I noticed that no log files are being generated now. I figured out it's not a problem with the SD card not being available because the config file gets read properly on startup, but an error is thrown when I attempt to open the log file for writing using fopen.
// Open the file
mLogFile = fopen(filename, "wb");
if(mLogFile == NULL)
{
printf("Error opening Log File [%d].\n", lnRetval);
return -1; //File couldn't be opened
}
I assumed it was just a permissions problem, but I can't understand why it doesn't work when I automatically start the software versus running it manually in a terminal. Furthermore, I can't understand why the config file gets read in properly but this file can't be opened.
The only difference I could see was that the config file reading is done using fstreams, while the logger is using C file I/O. So I experimented by placing the following code directly before the fopen call above (/home/root/etc is where the SD card is mounted).
std::ofstream out("/home/root/etc/log/testlog.log");
out << "I can write using fstreams.\n";
out.close();
That worked and generated the file when started through init.d. Now I'm completely stumped. Why does ofstream work and not fopen? Is there something fundamentally I'm missing?
Thanks in advance.
Your question does not provide enough information to answer, but the general approach to problems like this should be to run the program (in both forms) under strace and compare the sequence of syscalls made. That should quickly reveal what's happening differently. I suspect you'll just find the contents of filename are invalid...
Related
I'm opening a file for a video I'm creating and writing to disk with fopen in C++, I'm able to write to disk. But when I try to read it as I'm writing it, it will throw errors saying that it doesn't have permission to read the file as soon as I close the file or stop the program, I can suddenly read from it.
Not an issue with not finishing writing the write as if I crash the program, can still read it. Also, VLC's logs tell me it's a permission issue.
Any idea how to change that permission?
Response to William asking for code snippets or if open happened before the file existed:
Thanks William, here's what I've got. I waited a few minutes and could see the file with windows explorer by that point and waited until after I'd flushed and data was there, couldn't open with VLC or Notepad++ or Notepad or Windows Media Player
Notepad says cannot access because it is being used by another process, others too.
Here is the VLC log while it tries to open this:
http://snippi.com/s/g4cbu23
Here is where I create the file with fopen:
http://snippi.com/s/cyajw4h
At the very end is where I write to the file using fwrite and flush:
http://snippi.com/s/oz27m0g
You need to use _fsopen with _SH_DENYNO if you want the file to be shareable.
I need a logger for C++. And I found this post Small logger class, which led me to this simple logger http://www.drdobbs.com/cpp/201804215.
It mainly uses the following method to wirte to log file.
FILE* pFile = fopen("application.log", "a");
std::ostringstream os;
os<<"I am a log line."<<std::endl;
fprintf(pFile, "%s", os.str().c_str());
fflush(pFile);
But it doesn't work as I expected. I assume, with the log file open in notepad, each new log line would be showing immediately after fprintf and fflush. But it turned out that I have to close and reopen the file with notepad to see the update.
So is there a way to write log file in C++ that allows reading in real time, which makes the log file resemble win32 console or VS output window? I miss the days when I can dump everything to console.log in Javascript. :)
Thanks.
This is not a problem with your code, this is an issue with Notepad.
Notepad does not automatically check for changes in the file you have open.
Instead, you should use a tool that does, for instance Notepad++, or indeed most editors designed for programmers.
If you have installed cygwin, you could also use tail -f to monitor additions to the log file.
After the accepted answer from mjs pointed me in the right direction, I google searched "notepad auto refresh" and found this https://www.raymond.cc/blog/monitor-log-or-text-file-changes-in-real-time-with-notepad/.
It provides several options to monitor text file changes in Windows, including Notepad++ and other software specifically designed for monitoring text file changes, with features like keyword filter/highlight and save/load monitoring session.
You might find It interesting if you came across the same problem as mine. Cheers.
I have a Qt program that works on Linux but not on Windows. It progressively downloads something from the internet, writes that into the file, and then tries to open that file using QDesktopServices::openUrl. This works fine under Linux (Fedora), but when I run under Windows, nothing happens - the file is never opened, but also no error is reported.
However if I try to manually open the downloaded file on Windows, I find the reason for this. I get the error Another program is currently using this file, meaning that Qt has not released its lock on the file. However I have already called file->close() on it.
How can I ensure that all locks on a QFile have been released?
Here's a fragment of code that runs after the file has been written:
QString filename = file->fileName();
if (!file->flush())
emit error("Could not finish writing file") // Not emitted
file->close();
QDesktopServices::openUrl(QUrl::fromLocalFile(filename));
I don't think this is a Qt issue. I have seen similar behaviour on Windows systems before (with and without Qt), it might be that either the CRT or the OS still haven't finished their work on the file.
You might try to disable disk write caching in the OS to see, if things work as expected. I had to do this in a Windows-Embedded RT environment to get deterministic behaviour.
BTW: You can evaluate QFile::error() even after calling QFile::close() so you can skip your flush part completely.
C++ In Windows 7.
When writing to my log file, i sometimes set a breakpoint, or the program gets stuck at something. When i try too peek in my logfile from another program it says "The file cannot be opened because it is in use by another process". Well thats true, however I've worked with other programs that still allows reading from a logfile while they are writing to it, so I know it should be possible. Tried the _fsopen and unlocking the file but without success.
FILE* logFile;
//fopen_s(&logFile, "log.log", "w");
logFile = _fsopen("log.log", "w", _SH_DENYNO);
if (!logFile)
throw "fopen";
_unlock_file(logFile);
If you have the log-file open with full sharing-mode, others are still stopped from opening for exclusive access, or with deny-write.
Seems the second program wants more access than would be compatible.
Also, I guess you only want to append to the log, use mode "a" instead of "w".
Last, do not call _unlock_file unless you called _lock_file on the same file previously.
There is a way to do what you want though:
Open your file without any access, and then use Opportunistic Locks.
Raymond Chen's blog The Old New Thing also has a nice example: https://devblogs.microsoft.com/oldnewthing/20130415-00/?p=4663
When I use the std::ifstream to open a file that has been written in dos format, the ifstream does not seem to be able to open the file correctly since when I call good() on the stream afterwards it fails (returns false). I tried opening the file in binary mode as well as the default "in" mode and neither worked. If I convert the file to unix using dos2unix, everything works fine.
The goal behind being able to do this is that I want to be able to read a file and parse it, but I cannot guarantee that the file has not been saved in dos (Windows) or unix (Linux) format. Ideally, I would like to be able to use the ifstream.
Any suggestions?
Thanks!
The file format will NOT affect your ability to open it.
It is more likely that your path is not correct.
It seems extremely unlikely that GCC would do such a thing.
I suggest doing my_ifstream.exceptions( ios::failbit | ios::badbit ); before opening it, and running in the debugger. Then you can see where it ceased to be good.
Also, opening the file in binary mode (ios::in | ios::binary) should eliminate any possibility of the implementation being choosy over the contents of the file.