I'm dealing with fscanf function in C++ and I've confused point about fscanf. Why it doesn't block the calling thread while the stream is absolutely empty.
In my expectation, the main thread should be blocked on the fscanf function, it will be released after 3 seconds because the file stream is going to be written to after 3 seconds by the child thread.
But reality, it doesn't seem like I expected. Please somebody tells me why?
The following is my lines of code:
#include <windows.h>
#include <iostream>
#include <stdio.h>
DWORD WINAPI subroutine(LPVOID data)
{
FILE* file = (FILE*)data;
std::cout << "I'll send you something after 3s" << std::endl;
Sleep(3000);
if (file != NULL)
{
std::cout << "I'm writing now" << std::endl;
char* sentence = "Hello";
fputs(sentence, file);
}
}
int main()
{
FILE* file = tmpfile();
if ( file != NULL )
{
CreateThread(NULL, 0, subroutine, file, 0, NULL);
char something[50];
std::cout << "Blocking..." << std::endl;
rewind(file);
fscanf(file, "%s", something);
std::cout << "Message is " << something << std::endl;
}
std::cout << "Done" << std::endl;
if (file != NULL)
{
fclose(file);
}
return 0;
}
============
Because people may don't understand why I think fscanf should block the calling thread.
This is why I have the above question.
int main()
{
char something[50];
fscanf(stdin, "%s", something);
std::cout << something << std::endl;
return 0;
}
The program stopped to you enter something.
You are using a regular file, so when you are at its end fscanf returns EOF. The fact that there's another thread that in a few seconds will append some data is irrelevant, and the C library has no way to know it anyway.
Standard input blocks because when it is attached to a console it doesn't end (until the user presses Ctrl-D), so if you ask for more input and it's not ready to take it just waits (think to it as if it was a file on a disk extremely slow to provide the data).
Besides, using a FILE * backed by an actual file for cross-thread communication seems like a bad idea; besides the efficiency concerns and the headaches relative the thread-safety of sharing a FILE * between two threads, it maps badly to the problem at hand; what you seem to want here is a FIFO-like communication channel between two threads, not a storage device for data.
If you want to have FIFO communication between the two threads you can use - for example - an anonymous pipe or just a thread-safe message queue.
Related
I am encountering a problem when I am trying to write to sysfs node.
In the below code I am trying to wite to a trace_marker file. In the ftrace log, the first write is successful. But after that the write fails.
The file descriptor seemingly closes.
I do not want to open file every time before writing as writes are too frequent.
class Logger {
int mFileFd;
void logFromAnotherThread(std::string s) {
std::unique_lock<std::mutex> ul(mLogMu);
...
int count = write(mFileFd, s.c_str(), s.length());
if (count > 0)
std::cout << "Wrote n bytes: " << count << std::endl;
else
std::cout << "Errornum: " << strerror(errno) << std::endl;
...
}
Logger() {
mFileFd = open(SYSFS_NODE_WRITE, O_WRONLY);
....
}
}
First write is succesful.
I get output as-
Errornum: Bad file descriptor
My expectation is file open should be once, file descrtiptor should remain open for entire duration, and close on exit.
Edit 1:
Thank you for the suggestions on object getting destroyed. But I ensure that object is not getting destroyed.
For debugging, I had removed class/structure. Logging is now in simple C++ function calls. The file descriptor is a global variable, initialized once in main.
It does not works.
My confusion was is it something to do with the way write operations are performed on sysfs node.
Or can this be because of the number of writes are high (about 2-3 logs in 10us).
I am doing this like below, but this has an overhead of two added system calls.
#define TRACE_MARKER_FILE "/sys/kernel/debug/tracing/trace_marker"
void logdata(pid_t tid, std::string mystring) {
if(useLogger) {
std::stringstream ss;
if (funcname.length() > 0)
ss << LOGTAG << mystring;
int tempfd = open(TRACE_MARKER_FILE, O_WRONLY);
int count = write(tempfd, ss.str().c_str(), ss.str().length());
if (count == 0) {
std::cout << "Errornum: " << strerror(errno) <<std::endl;
}
close(tempfd);
}
}
I would suggest using std::ofstream which allows for proper RAII, in other words it will open the file in your constructor, then will automatically close the file in your destructor
class Logger {
std::ofstream mFile;
void logFromAnotherThread(std::string s) {
std::unique_lock<std::mutex> ul(mLogMu);
...
mFile << s;
...
}
Logger() : mFile(SYSFS_NODE_WRITE, O_WRONLY) {
....
}
}
Is it possible to set timeout for std::cin?
For example, std::cin doesn't receive any data during 10 seconds - it throws an exception or returns an error.
Edited:
And what about timer from Boost library? As far as I know, it is portable library. Is it possible to ask timer of Boost library to throw exceptions after predefined period of time? I guess it can solve this problem.
It isn't possible to set a time out for std::cin in a portable way. Even when resorting to non-portable techniques, it isn't entirely trivial to do so: you will need to replace std::cin's stream buffer.
On a UNIX system I would replace the default stream buffer used by std::cin by a custom one which uses file descriptor 0 to read the input. To actually read the input I would use poll() to detect presence of input and set a timeout on this function. Depending on the result of poll() I would either read the available input or fail. To possibly cope with typed characters which aren't forwarded to the file descriptor, yet, it may be reasonable to also turn off the buffering done until a newline is entered.
When using multiple threads you can create a portable filtering stream buffer which uses on thread to read the actual data and another thread to use a timed condition variable waiting either for the first thread to signal that it received data or for the time out to expire. Note that you need to guard against spurious wake-ups to make sure that the timeout is indeed reached when there is no input. This would avoid having to tinker with the actual way data is read from std::cin although it still replaces the stream buffer used by std::cin to make the functionality accessible via this name.
I just figured out how to do that, polling the std::cin file descriptor.
poll function returns 0 if timeout occurs and no event happened, 1 if something happened, and -1 if error happened.
#include <iostream>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
bool stop = false;
void intHandler(int dummy)
{
stop = true;
}
std::string readStdIn()
{
struct pollfd pfd = { STDIN_FILENO, POLLIN, 0 };
std::string line;
int ret = 0;
while(ret == 0)
{
ret = poll(&pfd, 1, 1000); // timeout of 1000ms
if(ret == 1) // there is something to read
{
std::getline(std::cin, line);
}
else if(ret == -1)
{
std::cout << "Error: " << strerror(errno) << std::endl;
}
}
return line;
}
int main(int argc, char * argv[])
{
signal(SIGINT, intHandler);
signal(SIGKILL, intHandler);
while(!stop)
{
std::string line = readStdIn();
std::cout << "Read: " << line << std::endl;
}
std::cout << "gracefully shutdown" << std::endl;
}
There was a good answer posted here but the author removed it. It's a solution that worked well for me in the application I was developing. This is the essence of what the person wrote:
// compile: g++ -pthread thisfile.cpp
#include <iostream>
#include <thread>
int main() {
int x;
bool inputReceived = false;
time_t startTime = time(NULL);
time_t waitTime = 10;
std::cout << "Enter a number within " << waitTime << " seconds\n";
// spawn a concurrent thread that waits for input from std::cin
std::thread t1([&]() {
std::cin >> x;
inputReceived = true;
});
t1.detach();
// check the inputReceived flag once every 50ms for 10 seconds
while (time(NULL) < startTime + waitTime && !inputReceived) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
if (inputReceived) {
std::cout << "x = " << x << "\n";
return EXIT_SUCCESS;
}
std::cout << "timeout\n";
// TODO: find a way to kill the thread
return EXIT_FAILURE;
}
Be aware that the thread continues running after the timeout occurs, but it will terminate when the whole program terminates. If this is all you need then you don't need to worry about it.
However, there is no simple way to kill a detached thread. A solution would be to close the input stream, but that's not easy or desirable to do with std::cin. If you're lucky then you're going to use this with an easily closeable stream instead of std::cin. Closing the stream will cause input statement to fail and the the thread will probably just exit with an internal exception, but at least the thread will terminate.
This question already has answers here:
How to construct a c++ fstream from a POSIX file descriptor?
(8 answers)
Closed 2 years ago.
I'm new to programming, and I'm trying to write a c++ program for Linux which would create a child process, and this child process would execute an external program. The output of this program should be redirected to the main program and saved into a string variable, preserving all the spaces and new lines. I don't know how many lines/characters will the output contain.
This is the basic idea:
#include <iostream>
#include <string>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int pipeDescriptors[2];
pipe(pipeDescriptors);
pid_t pid = fork();
if (pid == -1)
{
std::cerr << __LINE__ << ": fork() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
else if (!pid)
{
// Child process
close(pipeDescriptors[0]); // Not gonna read from here
if (dup2(pipeDescriptors[1], STDOUT_FILENO) == -1) // Redirect output to the pipe
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
close(pipeDescriptors[1]); // Not needed anymore
execlp("someExternalProgram", "someExternalProgram", NULL);
}
else
{
// Parent process
close(pipeDescriptors[1]); // Not gonna write here
pid_t stdIn = dup(STDIN_FILENO); // Save the standard input for further usage
if (dup2(pipeDescriptors[0], STDIN_FILENO) == -1) // Redirect input to the pipe
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
close(pipeDescriptors[0]); // Not needed anymore
int childExitCode;
wait(&childExitCode);
if (childExitCode == 0)
{
std::string childOutput;
char c;
while (std::cin.read(&c, sizeof(c)))
{
childOutput += c;
}
// Do something with childOutput...
}
if (dup2(stdIn, STDIN_FILENO) == -1) // Restore the standard input
{
std::cerr << __LINE__ << ": dup2() failed!\n" <<
std::strerror(errno) << '\n';
return 1;
}
// Some further code goes here...
}
return 0;
}
The problem with the above code is that when std::cin.get() function reads the last byte in the input stream, it doesn't actually "know" that this byte is the last one and tries to read further, which leads to set failbit and eofbit for std::cin so I cannot read from the standard input later anymore. std::cin.clear() resets those flags, but stdin still remains unusable.
If I could get the precise size in bytes of the stdin content without going beyond the last character in the stream, I would be able to use std::cin.read() for reading this exact amount of bytes into a string variable. But I guess there is no way to do that.
So how can I solve this problem? Should I use an intermediate file for writing the output of the child process into it and reading it later from the parent process?
The child process writes into the pipe but the parent doesn't read the pipe until the child process terminates. If the child writes more than the pipe buffer size it blocks waiting for the parent to read the pipe, but the parent is blocked waiting for the child to terminate leading to a deadlock.
To avoid that, the parent process must keep reading the pipe until EOF and only then use wait to get the child process exit status.
E.g.:
// Read entire child output.
std::string child_stdout{std::istreambuf_iterator<char>{std::cin},
std::istreambuf_iterator<char>{}};
// Get the child exit status.
int childExitCode;
if(wait(&childExitCode))
std::abort(); // wait failed.
You may also like to open a new istream from the pipe file descriptor to avoid messing up std::cin state.
I need a program to communicate with a subprocess that is relying on in- and
output. The problem is that I am apparently not able to use QProcess correctly.
The code further down should create a QProcess, start it and enter the main while loop. In there it prints all the output created by the subprocess to the console and subsequently asks the user for input which is then passed to the subprocess via write(...).
Originally I had two problems emerging from this scenario:
The printf's of the subprocess could not be read by the parent process.
scanf in the subprocess is not receiving the strings sent via write.
As for (1), I came to realize that this is a problem caused by the buffering of the subprocess' stdout. This problem can be solved easily with fflush(stdout) calls or manipulations regarding its flushing behavior.
The second problem is the one I can't wrap my head around. write gets called and even returns the correct number of sent bytes. The subprocess, however, is not continuing its excecution, because no new data is written to its output. The scanf seems not to be receiving the data sent. The output given by the program is:
Subprocess should have started.
124 bytes available!
Attempting to read:
Read: This is a simple demo application.
Read: It solely reads stdin and echoes its contents.
Read: Input exit to terminate.
Read: ---------
Awaiting user input: test
Written 5 bytes
No line to be read...
Awaiting user input:
I am seriously stuck right here. Google + heavy thinking having failed on me, I want to pass this on to you as my last beacon of hope. In case I am just failing to see the forest for all the trees, my apologies.
In case this information is necessary: I am working on 64bit MacOS X using Qt5 and the clang compiler. The subprocess-code is compiled with gcc on the same machine.
Thank you very much in advance,
NR
Main-Code:
int main() {
// Command to execute the subprocess
QString program = "./demo";
QProcess sub;
sub.start(program, QProcess::Unbuffered | QProcess::ReadWrite);
// Check, whether the subprocess is starting correctly.
if (!sub.waitForStarted()) {
std::cout << "Subprocess could not be started!" << std::endl;
sub.close();
return 99;
}
std::cout << "Subprocess should have started." << std::endl;
// Check, if the subprocess has written its starting message to the output.
if (!sub.waitForReadyRead()) {
std::cout << "No data available for reading. An error must have occurred." << std::endl;
sub.close();
return 99;
}
while (1) {
// Try to read the subprocess' output
if (!sub.canReadLine()) {
std::cout << "No line to be read..." << std::endl;
} else {
std::cout << sub.bytesAvailable() << " bytes available!" << std::endl;
std::cout << "Attempting to read..." << std::endl;
while (sub.canReadLine()) {
QByteArray output = sub.readLine();
std::cout << "Read: " << output.data();
}
}
std::cout << "Awaiting user input: ";
std::string input;
getline(std::cin, input);
if (input.compare("exit") == 0) break;
qint64 a = sub.write(input.c_str());
qint64 b = sub.write("\n");
sub.waitForBytesWritten();
std::cout << "Written " << a + b << " bytes" << std::endl;
}
std::cout << "Terminating..." << std::endl;
sub.close();
}
Subprocess-Code:
int main() {
printf("This is a simple demo application.\n");
printf("It reads stdin and echoes its contents.\n");
printf("Input \"exit\" to terminate.\n");
while (1) {
char str[256];
printf("Input: ");
fflush(stdout);
scanf("%s", str);
if (strcmp(str, "exit") == 0) return 0;
printf("> %s\n", str);
}
}
P.s: Since this is my first question on SO, please tell me if something is wrong concerning the asking style.
Solution
After many many more trials & errors, I managed to come up with a solution to the problem. Adding a call to waitForReadyRead() causes the main process to wait until new output is written by the subprocess. The working code is:
...
sub.waitForBytesWritten();
std::cout << "Written " << a + b << " bytes" << std::endl;
// Wait for new output
sub.waitForReadyRead();
...
I still don't have a clue why it works this way. I guess it somehow relates to the blocking of the main process by getline() vs blocking by waitForReadyRead(). To me it appears as if getline() blocks everything, including the subprocess, causing the scanf call never to be processed due to race conditions.
It would be great, if someone who understands could drop an explanation.
Thank you for your help :)
NR
This will not work. You are waiting for the sent bytes to be written but you are not waiting for the echo. Instead you are entering the getline() function waiting for new user input. Keep in mind that two processes are involved here where each process can be delayed to any degree.
Apart from this you should consider building your Qt application asynchronously (having an event loop) instead of trying the synchronous approach. This way your Qt application can do things in parallel... e.g. reading input or waiting for input from the remote process while still not being blocked and able to accept user input.
I'm trying to use the ofstream class to write some stuff to a file, but all that happens is that the file gets created, and then nothing. I have some simply code here:
#include <iostream>
#include <fstream>
#include <cstring>
#include <cerrno>
#include <time.h>
using namespace std;
int main(int argc, char* argv[])
{
ofstream file;
file.open("test.txt");
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
for (int i = 0; i < 10; i++) {
file << i << "\t" << time(NULL) << endl;
}
file.flush();
file.close();
return 0;
}
When I create a console application, everything works fine, so I'm afraid this code is not completely representative. However, I am using code like this in a much larger project that - to be honest - I don't fully understand (Neurostim). I'm supposed to write some class that is compiled to a dll which can be loaded by Neurostim.
When the code is run, "test.txt" is created and then "No error!" is printed, as this is apparently the output from strerror. Obviously this is wrong however. The application runs perfectly otherwise, and is not phased by the fact that I'm trying to write to a corrupted stream. It just doesn't do it. It seems to me like there is no problem with permissions, because the file is in fact created.
Does anyone have any ideas what kind of things might cause this odd behavior? (I'm on WinXP Pro SP3 and use Visual C++ 2008 Express Edition)
Thanks!
Just a thought :- in your real code are you re-using your stream object?
If so, you need to ensure that you call clear() on the stream before re-using the object otherwise, if there was a previous error state, it won't work. As I recall, not calling clear() on such a stream would result in an empty file that couldn't be written to, as you describe in your question.
ofstream file;
file.open("test.txt");
Just a nit: you can combine that into a single line. ofstream file("test.txt");
if (file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Your test is backwards. If file is true, it's open and ready for writing.
Also, I wouldn't count on strerror() working correctly on Windows. Most Windows APIs don't use errno to signal errors. If your failure is happening outside the C/C++ run-time library, this may not tell you anything interesting.
UPDATE Thinking more about this, failing to open a file via fstreams is not guaranteed to set errno. It's possible that errno ends up set on some platforms (espeically if those platforms implement fstream operations with FILE* or file descriptors, or some other library that sets errno) but that is not guaranteed. The official way to check for failure is via exceptions, std::io_state or helper methods on std::fstream (like fail or bad). Unfortunately you can't get as much information out of std::streams as you can from errno.
You've got the if statement wrong. operator void* returns NULL (a.k.a. false) if the file is not writable. It returns non-zero (a.k.a. true) if the file is writeable. So you want:
if (!file) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}
Or:
if (!file.good()) {
cout << strerror(errno) << endl;
} else {
cout << "All is well!" << endl;
}