File I/O across processes in Linux? - c++

So, I've got a Linux process where I'm trying to manage some files on a tape. I have the following code that attempts to extract a file, catalog.xml, from the current archive on the tape and copy it to a fixed location (eventually, I'll parse the file and do some work with the results). But, my code is intermittently failing to work correctly. The tar command always succeeds, (and if I check the file system, I see the catalog.xml file), but sometimes my followup check to see if the file exists returns false. Am I doing something obviously wrong? It seems like I'm probably encountering a race condition between the fork()ed process returning and the results of that process being visible on the file system - is there some call I need to make?
pid_t tPid = vfork();
if (0 == tPid)
{
int tChildRet;
tChildRet = execlp("tar", "tar", "-xvf", "/dev/nst0", "-C", "/tmp", "catalog.xml", (char *) 0);
_exit(-1 == tChildRet ? EXIT_FAILURE : EXIT_SUCCESS);
}
else
{
wait(&ret);
}
std::ifstream tCatalogFile("/tmp/catalog.xml");
if (tCatalogFile)
{
cout << "File exists!" << endl;
} else {
cout << "File does not exist!" << endl;
}
And I'm getting either "file exists!" or "file does not exist!", seemingly at random.
Other notes:
On the failure cases:
if I do a stat ("/tmp/catalog.xml"), I get a return of -1 with errno set to ENOENT.
the tar command (run with the -v flag) produces the expected one line of output ("catalog.xml")
/tmp is a local tmpfs filesystem; the tape drive is a local device.
I'm using 2.6.30.9 Linux kernel with g++ 4.1.2 on a x86_64 box.
Thanks in advance!

Try calling sync after the wait call in the parent.
If that doesn't work, you may need to loop and/or sleep until the parent can open the file, since you know it's there.

If execlp succeeds, it will never get to the line where you call _exit. You aren't checking the return value (ret) from wait. It's not clear why you should be using vfork. Etc.
Since the parent is not doing anything else besides waiting for the child to complete, why not make your life easier and just use system()?

Related

Program doesn't stop after returning 0 from main

I wrote a program that encodes files with Huffman coding. It works fine but for some reason after returning 0 from main function it doesn't stop.
Main function looks like:
int main(int argc, char *argv[])
{
if (argc < 5)
{
std::cout << "..." << std::endl;
}
else
{
if (!std::strcmp(argv[1], "haff") && !std::strcmp(argv[2], "-c"))
HuffmanC(argv[3], argv[4]);
if (!std::strcmp(argv[1], "haff") && !std::strcmp(argv[2], "-d"))
HuffmanD(argv[3], argv[4]);
std::cout << "Operations: " << count << std::endl;
}
return 0;
}
When I run it, I get:
MacBook-Pro-Alex:code alex$ ./main haff -c test.txt test.haffOperations: 37371553
It ends with an empty line and terminal says that the program keeps running, but the last cout statement executes well and as I get it it should return 0 and finish. How can I make it finish after returning 0? Or is the problem in the rest of the code?
Or is the problem in the rest of the code?
Possibly. Perhaps you've corrupted your stack somehow, so that you're "returning" from main to someplace you didn't expect. We can't really know without an complete, verifiable example.
How can I make it finish after returning 0?
You can use the kill command on MacOS to terminate it forcefully. Using the GUI task manager may or may not work.
But perhaps a more effective course of action would be to attach a debugger to the process and see what it's actually doing.
You could read this explanation on how to do this on MacOS with XCode - but I don't use MacOS, so I wouldn't know. Also, #SergeyA graciously suggests trying using pstack to get the process' current stack. Of course, if the stack has been garbled, there's no telling what you'll actually get.
Make sure the application is compiled with debugging information included.
Finally - it's probably better to run the program with a debugger attached in the first place, and set a breakpoint at the last cout << line.

std system is run after going to next line c++

here is piece of my code:
void Espresso::run()
{
std::system("/home/espresso-ab-1.0/src/espresso espresso.in > espresso.out");
std::string line;
std::ifstream myfile ("espresso.out");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::cout << line << '\n';
}
myfile.close();
}
}
I am wondering if above code first run the system command and fill completely "espresso.out" file and then go to the the next line of reading it.
if not, how I can make sure file is fully printed before going to read it.
NOTE: I am restricted to use C++03.
Thanks for your prompt answer. I want to Update my question by:
- Is it a thread safe method as well?
std::system is not an async function. So for example, if you'd run:
std::system("sleep 5");
std::cout << "Foo" << std::endl;
"Foo" will be displayed after 5 seconds.
Of course if you're on linux you could run it like this std::system("sleep 5 &"). Then the sleep command will run as a background process and the code following the system call will execute immediately.
Although I encourage you not to use this function. Calling system functions by their name is dangerous. Imagine what would happen, if someone replaced the sleep binary in your system with their own program. Conclusion: your program will hang until the system command is completed. So your file will be ready.
Yes, the command will be fully completed before the std::system call returns.

pidof from a background script for another background process

I wrote a c++ program to check if a process is running or not . this process is independently launched at background . my program works fine when I run it on foreground but when I time schedule it, it do not work .
int PID= ReadCommanOutput("pidof /root/test/testProg1"); /// also tested with pidof -m
I made a script in /etc/cron.d/myscript to time schedule it as follows :-
45 15 * * * root /root/ProgramMonitor/./testBkg > /root/ProgramMonitor/OutPut.txt
what could be the reason for this ?
string ReadCommanOutput(string command)
{
string output="";
int its=system((command+" > /root/ProgramMonitor/macinfo.txt").c_str());
if(its==0)
{
ifstream reader1("/root/ProgramMonitor/macinfo.txt",fstream::in);
if(!reader1.fail())
{
while(!reader1.eof())
{
string line;
getline(reader1,line);
if(reader1.fail())// for last read
break;
if(!line.empty())
{
stringstream ss(line.c_str());
ss>>output;
cout<<command<<" output = ["<<output<<"]"<<endl;
break;
}
}
reader1.close();
remove("/root/ProgramMonitor/macinfo.txt");
}
else
cout<<"/root/ProgramMonitor/macinfo.txt not found !"<<endl;
}
else
cout<<"ERROR: code = "<<its<<endl;
return output;
}
its output coming as "ERROR: code = 256"
thanks in advacee .
If you really wanted to pipe(2), fork(2), execve(2) then read the output of a pidof command, you should at least use popen(3) since ReadCommandOutput is not in the Posix API; at the very least
pid_t thepid = 0;
FILE* fpidof = popen("pidof /root/test/testProg1");
if (fpidof) {
int p=0;
if (fscanf(fpidof, "%d", &p)>0 && p>0)
thepid = (pid_t)p;
pclose(fpidof);
}
BTW, you did not specify what should happen if several processes (or none) are running the testProg1....; you also need to check the result of pclose
But you don't need to; actually you'll want to build, perhaps using snprintf, the pidof command (and you should be scared of code injection into that command, so quote arguments appropriately). You could simply find your command by accessing the proc(5) file system: you would opendir(3) on "/proc/", then loop on readdir(3) and for every entry which has a numerical name like 1234 (starts with a digit) readlink(2) its exe entry like e.g. /proc/1234/exe ...). Don't forget the closedir and test every syscall.
Please read Advanced Linux Programming
Notice that libraries like Poco or toolkits like Qt (which has a layer QCore without any GUI, and providing QProcess ....) could be useful to you.
As to why your pidof is failing, we can't guess (perhaps a permission issue, or perhaps there is no more any process like you want). Try to run it as root in another terminal at least. Test its exit code, and display both its stdout & stderr at least for debugging purposes.
Also, a better way (assuming that testProg1 is some kind of a server application, to be run in at most one single process) might be to define different conventions. Your testProg1 might start by writing its own pid into /var/run/testProg1.pid and your current application might then read the pid from that file and check, with kill(2) and a 0 signal number, that the process is still existing.
BTW, you could also improve your crontab(5) entry. You could make it run some shell script which uses logger(1) and (for debugging) runs pidof with its output redirected elsewhere. You might also read the mail perhaps sent to root by cron.
Finally I solved this problem by using su command
I have used
ReadCommanOutput("su -c 'pidof /root/test/testProg1' - root");
insteadof
ReadCommanOutput("pidof /root/test/testProg1");

Strange behavior with boost file_sink when forking

I'm observing some strange behavior when I use a file_sink (in boost::iostreams) and then fork() a child process.
The child continues the same codebase, i.e., no exec() call, because this is done as part of daemonizing the process. My full code fully daemonizaes the process, of course, but I have omitted those steps that are unncessary for reporducing the behavior.
The following code is a simplified example that demonstrates the behavior:
using namespace std;
namespace io = boost::iostreams;
void daemonize(std::ostream& log);
int main (int argc, char** argv)
{
io::stream_buffer<io::file_sink> logbuf;
std::ostream filelog(&logbuf);
//std::ofstream filelog;
// Step 1: open log
if (argc > 1)
{
//filelog.open(argv[1]);
logbuf.open(io::file_sink(argv[1]));
daemonize(filelog);
}
else
daemonize(std::cerr);
return EXIT_SUCCESS;
}
void daemonize(std::ostream& log)
{
log << "Log opened." << endl;
// Step 2: fork - parent stops, child continues
log.flush();
pid_t pid = fork(); // error checking omitted
if (pid > 0)
{
log << "Parent exiting." << endl;
exit(EXIT_SUCCESS);
}
assert(0 == pid); // child continues
// Step 3: write to log
sleep(1); // give parent process time to exit
log << "Hello World!" << endl;
}
If I run this with no argument (e.g., ./a.out), so that it logs to stderr, then I get the expected output:
Log opened.
Parent exiting.
Hello World!
However, if I do something like ./a.out temp; sleep 2; cat temp then I get:
Log opened.
Hello World!
So the parent is somehow no longer writing to the file after the fork. That's puzzle #1.
Now supposed I just move io::stream_buffer<io::file_sink> logbuf; outside of main so that it's a global variable. Doing that and simply running ./a.out gives the same expected output as in the previous case, but writing to a file (e.g., temp) now gives a new puzzling behavior:
Log opened.
Parent exiting.
Log opened.
Hello World!
The line that writes "Log opened." is before the fork() so I don't see why that should appear twice in the output. (I even put an explicit flush() immediate before the fork() to make sure that line of output wasn't simply buffered, and then the buffer got copied during the fork() and later both copies eventually flushed to the stream...) So that's puzzle #2.
Of course, if I comment out the whole fork() process (the entire section labeled as "Step 2") then it behaves as expected for both file and stderr output, and regardless of whether logbuf is global or local to main().
Also, if I switch filelog to be an ofstream instead of stream_buffer<file_sink> (see commented out lines in main()) then it also behaves as expected for both file and stderr output, and regardless of whether filelog/logbuf are global or local to main().
So it really seems that it's an interaction between file_sink and fork() producing these strange behaviors... If anyone has ideas on what may be causing these, I'd appreciate the help!
I think I got it figured out... creating this answer for posterity / anyone who stumbles on this questions looking for an answer.
I observed this behavior in boost 1.40, but when I tried it using boost 1.46 everything behaved in the expected manner in all cases, i.e.:
Log opened.
Parent exiting.
Hello World!
So my assumption right now is that this was actually a bug in boost that was fixed sometime between version 1.41-1.46. I didn't see anything in the release notes that made it real obvious to me that they found & fixed the bug, but it's possible the release notes discussed fixing some underlying cause of this bug and I wasn't able to make the conneciton between that underlying cause and this scenario.
In any case, the solution seems to be to install boost version >= 1.46

How to prevent a Linux program from running more than once?

What is the best way to prevent a Linux program/daemon from being executed more than once at a given time?
The most common way is to create a PID file: define a location where the file will go (inside /var/run is common). On successful startup, you'll write your PID to this file. When deciding whether to start up, read the file and check to make sure that the referenced process doesn't exist (or if it does, that it's not an instance of your daemon: on Linux, you can look at /proc/$PID/exe). On shutdown, you may remove the file but it's not strictly necessary.
There are scripts to help you do this, you may find start-stop-daemon to be useful: it can use PID files or even just check globally for the existence of an executable. It's designed precisely for this task and was written to help people get it right.
Use the boost interprocess library to create a memory block that will be created by the process. If it already exists, it means that there is another instance of the process. Exit.
The more precise link to what you need would be this one.
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/scoped_ptr.hpp>
int main()
{
using boost::interprocess;
boost::scoped_ptr<shared_memory_object> createSharedMemoryOrDie;
try
{
createSharedMemoryOrDie.reset(
new shared_memory_object(create_only, "shared_memory", read_write));
} catch(...)
{
// executable is already running
return 1;
}
// do your thing here
}
If you have access to the code (i.e. are writing it):
create a temporary file, lock it, remove when done, return 1; if file exists, or,
list processes, return 1; if the process name is in the list
If you don't:
create a launcher wrapper to the program that does one of the above
I do not know what your exact requirement is but I had a similar requirement; in that case I started my daemon from a Shell script ( it was a HP-UX machine) and before starting the daemon I checked if an exec by same name is already running. If it is; then don't start a new one.
By this way I was also able control the number of instances of a process.
I think this scheme should work (and is also robust against crashes):
Precondition: There is a PID file for your application (typically in /var/run/)
1. Try to open the PID file
2. If it does not exist, create it and write your PID to it. Continue with the rest of the program
3. If it exist, read the PID
4. If the PID is still running and is an instance of your program, then exit
5. If the PID does not exist or is used by another program, remove the PID file and go to step 2.
6. At program termination, remove the PID file.
The loop in step 5 ensures that, if two instances are started at the same time, only one will be running in the end.
Have a pid file and on the startup do a 'kill -0 <pid>'. Where is the value read from file. If the response is != 0 then the daemon is not alive and you might restart it
Another approach would be to bind to a port and handle the bind exception on the second attempt to start the daemon. If the port is in use then exit otherwise continue running the daemon.
I believe my solution is the simplest:
(don't use it if racing condition is a possible scenario, but on any other case this is a simple and satisfying solution)
#include <sys/types.h>
#include <unistd.h>
#include <sstream>
void main()
{
// get this process pid
pid_t pid = getpid();
// compose a bash command that:
// check if another process with the same name as yours
// but with different pid is running
std::stringstream command;
command << "ps -eo pid,comm | grep <process name> | grep -v " << pid;
int isRuning = system(command.str().c_str());
if (isRuning == 0) {
cout << "Another process already running. exiting." << endl;
return 1;
}
return 0;
}