std::cout and gfortran print*, don't output to the screen

I am not sure where to post this other than here.

I am trying to figure out why an app gives different output when compiled under Ubuntu 10.10 and CentOS 5.5. I am pretty sure that the issue is that the Cent version has gcc 4.1 installed, while Ubuntu has gcc 4.4. I am trying to print from some fortran code using print*, as I have always done, but nothing appears on the terminal. I don't know how to debug this if I can't print any intermediary output.

I also tried std::cout << from inside the cpp code, but that doesn't do anything either. There aren't any compiler errors or warnings, so what did I miss? :wall:

Any suggestions???

LMHmedchem

Hi.

It seems to work for me:

#!/usr/bin/env bash

# @(#) s1	Demonstrate compile, execute with gfortran, g++.

# Utility functions: print-as-echo, print-line-with-visual-space, debug.
pe() { for i;do printf "%s" "$i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
db() { ( printf " db, ";for i;do printf "%s" "$i";done; printf "\n" ) >&2 ; }
db() { : ; }
C=$HOME/bin/context && [ -f $C ] && . $C g++ gfortran

pl " File hi.f:"
cat hi.f

pl " Results, hi.f:"
rm -f a.out
gfortran hi.f
./a.out

pl " File hi.cpp:"
cat hi.cpp

pl " Results, hi.cpp:"
rm -f a.out
g++ hi.cpp
./a.out

rm -f a.out

exit 0

producing:

$ ./s1

Environment: LC_ALL = C, LANG = en_US.UTF-8
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.18-194.32.1.el5, i686
Distribution        : CentOS release 5.5 (Final) 
GNU bash 3.2.25
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
gfortran GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)

-----
 File hi.f:
	program hi
	write(*,*) " Hello, world with write * *"
	print*, " Hello, world with print *"
	end

-----
 Results, hi.f:
  Hello, world with write * *
  Hello, world with print *

-----
 File hi.cpp:
#include <iostream>

using namespace std;

int main()
{
  cout << " Hello, world from c++ with cout" << endl;
  return ( 0 );
}

-----
 Results, hi.cpp:
 Hello, world from c++ with cout

Standard advice:

Best wishes ... cheers, drl

I think that the root of the problem is that this is a parent child pair of programs. The parent uses fork to create a child process, and I am trying to print from the child process code. Under Cygwin windows, adding print statements results in output to the cygwin bash shell, but for some reason this doesn't seem to work under linux. There are some differences in the code base because of the differences in windows and posix pipes, fork/create_process, etc. I suspect that in linux, the child runs in a background shell, or something like that, and so the output doesn't come to the terminal that launched the parent, if that makes any sense.

Is there any way to test this theory or resolve the issue if I am correct?

LMHmedchem

Child processes should print to the terminal fine unless you created them in a very strange way. After all, every single command you run in a shell is a child process...

Whether this is true or not I cannot begin to guess because I can't see your computer from here, so have no more than a vague description that you "might" have done something in an odd way.

Is it something you did? Maybe. Maybe not. Post the code.

The only reference to fork is, ichpid = fork(); and then ichpid is used.

I can't post all of this code without various kinds of permission. I have a version of it that has been cleared, but it will take a bit to add the linux components and such. The cleared version is the widows code.

I just don't under stand why it doesn't print to the terminal. I have tried in CentOS, and Ubuntu and get the same results. There are no fortran header files, so there can't be a missing include, even if the compiler would let it go. Am I missing a compiler flag or something like that? I could post the make file if that would help. The only difference between the windows and linux versions are the src files for the parent and child main functions, and an auxilary functions src file. That is a very small part of the code and the rest is the same for win/lin. I don't really understand why this works in cygwin bash, but not linux bash. Both are using the gcc3.4 family.

LMHmedchem

The fork isn't relevant. What's relevant is what redirections have been done before and/or after it, if any.

How do you know it's printing at all?

Moving a sick sheep from place to place won't fix the sheep.

There's no "stop consoles from working" compiler flag, no. I suspect it's something internal to the program.

Not really.

I suspect differences in paths and such are preventing sub-programs from launching. Remember that UNIX in general is case-sensitive while Windows is not.

Trace every step of the process. Put print statements in places so you can see where the execution stops.

Of course, I'm only making wild guesses. Without seeing the code that's the best any of us can do.

Hi.

So with me and Windows.

In case you missed the earlier entry:

That may mean that you may need to do some coding to try to elicit the symptoms with the smallest code. If you are reluctant, then we can be of little of no help.

I am disengaging from this thread.

Best of luck ... cheers, drl

1 Like

The problem is particularly odd because the program compiles, links, runs, and gives the correct output, it just doesn't print to the screen. That would rule out control never reaching the print statement and such.

I was trying to debug a difference in output between the windows and linux versions, but I was able to correct that by compiling the linux under gcc3.4 instead of 4.1. Changes to the gcc header files are what "...causeth my head to ache", among other things. So now the app works properly when compiled under linux, but I still can't get anything to print to the screen??? I thought I would try to run that down, since I am sure I will need to be able to do it.

I will try to duplicate the situation in a smaller piece of code I can post. The parent main is in cpp, which forks a cpp child, that calls fortran functions, which in turn call cpp functions, so tracking things down can be a bit dodgy. I am also trying to get a hold of the person who wrote that part of the code, so I will post back if he has anything to add.

LMHmedchem

If it doesn't print to the screen, what does it print to?

There's no mysterious difference between cygwin terminal inheritance and linux terminal inheritance that causes terminals to break. If anything I'd expect it to break in cygwin first since it's generally a poor approximation of UNIX. It comes down to what your program is doing, or maybe what the script running it is doing.

Beyond that I can't help if you can't post code. I've thrown as many darts at as many possible answers as I can think of. I'm done with this thread too.

The parent creates an output file with a printing function.

This is the code that prints the header row of the output.

void printSfileHeader1ln( std::ostream &ros, const Remapper & re, 
                          char cdelim, int ihowmany, int bLegacy)
{
   int ii, i2, ihowmany2;
   char pszFormat[10]; // beware below
   if(ihowmany > re.max_can_print() ) {
      fprintf(stderr, "printSfileHeader1ln: ihowmany over bounds: %d vs %d\n",
               ihowmany, re.max_can_print() );
      return;
   }
   ihowmany2 = (ihowmany >= re.max_can_print() ) ? re.max_can_print() : ihowmany;

   if( bLegacy & EXTRA_NEWLINES )
      ros << "aname\n";
   else
   {
      ros << "aname";
   }

   if( re.xlations_computed() ) 
      ii = 0;
   else if( bLegacy & NO_SEQUENCE_CT ) 
      ii = 1; // this will suppress the "id" index
   else
      ii = 0;
   for(;ii< ihowmany2; ii++) {
      i2 = ii;
      ros << cdelim << re.desname[i2];
   }
   ros << "\n";
   
   if( bLegacy & EXTRA_NEWLINES )
      ros << "$$$$\n";
}

The same code is used for printing in both windows and linux (same src file).

LMHmedchem

And does it succeed in creating that file?

---------- Post updated at 11:13 AM ---------- Previous update was at 11:01 AM ----------

If the stderr output doesn't appear, it's because some step along the way is redirecting it. Check the script files you're running it with. 2> /dev/null and the like will prevent you from seeing stderr output. It's also possible for code inside your program to alter stderr.

Yes it does successfully create the output file, and I have carefully checked it to see that the content is correct.

I am just running the app with a very simple command line string "./appName -i inputFile -o outputFile". I do re-direct to a file with > or &> when I am generating allot of output, but not in this case.

I will start adding print statements at the beginning of the parent function and work my way through to see if this issue holds true in all parts of the code or is an issue local to some specific function(s).

LMHmedchem

It'd help if you answered some of my questions too...

If I understand you, you want things in outputFile to also appear in the terminal as it goes?

If ros is an output file, and only an output file, I wouldn't have ever expected its output to go anywhere but the output file -- not even in Windows. Things going to stderr should still appear in the terminal of course, and if they're not, please tell me so.

I think something external to the application was following the file and printing its output to terminal. You can print a file being written to to terminal with tail -f by doing something like this:

# Blank the output file
: > outputFile
exec 5<outputFile
# Run tail -f in the background, save its PID
tail -f <&5 &
PID=$!
# Close the PID in the shell, we don't need it anymore
exec 5<&-

application -o outputFile
# wait a moment for tail to finish
sleep 1
# kill it
kill "$PID"
# wait for tail to quit
wait

If you can convince your application to print to standard output, this becomes far simpler:

application | tee outputFile

Sorry for the delay in responding, I had to go to the doctors. I have been trying to get rid of an annoying case of bronchitis. It would help if it would just get warm some time soon.

Did I miss something somewhere? I thought I answered everything.

Maybe I wasn't clear in the original post. The issue is not with the output that the program is supposed to make, which goes to the output file (and is working properly), but with additional print statements that I have added for debugging purposes. Since I can't get fortran to work with gdb, I am stuck without a debugger/IDE and have to debug by adding print statements to the code in very, very, old school fashion.

I normally just add,
print*, (fortran)
std::cout << (cpp)
and get the output I need.

This is the code that I can't get to print to the terminal in linux, but prints fine in windows. The normal output file is fine under both platforms.

I would normally just run,

./appName -i inputFile -o outputFile
./appName -i inputFile -o outputFile > stdout.txt (for large output)

and could look at the debugging output in the shell. The program runs, the output is fine, but there is nothing in the shell, or output fie (I tested both).

I have also tried,

./appName -i inputFile -o outputFile &> stdout.txt

in case the output was somehow going to stderr.

The only thing I can think of is that cout is not going to the terminal in this case, but has been redirected elsewhere, like it might be if you were running a gui. I will look carefully through the code and see if I can spot anything that might be a likely candidate. It was also suggested that the problem may be with flushing the o/p buffer, so I will also try adding some cin statements and see if that changes anything.

LMHmedchem

Bronchitis is no fun. :frowning: Get well soon.

Thank you, now we finally know what you want.

Flushing shouldn't matter, anything still in the buffers will be printed before the program exits -- unless your program crashes or is killed by a signal. In that case buffers won't be flushed.

It's probably a better idea to print debug messages to stderr or cerr in general. They never buffer, and won't get mixed in with any data you were expecting on stdout/cout.

If you're using cin/cout/cerr, you should stick to cin/cout/cerr and not use stdin/stdout/stderr. Or vice versa. They compete for the same resources and could conceivably cause each other problems.

If your program isn't crashing and you're not mixing stdio+iostreams and you're still not getting output, something must be closing or redirecting these streams or file descriptors. Try putting this into your program somewhere:

system("ls -l /proc/self/fd > /path/to/files.txt");

which should print a list of what files and terminals and sockets your application has open into /path/to/files.txt

Thank you so much for your help so far. I just took some medicine and I need to lie down for a while, so I don't fall off my d**n chair. I will add the system ls line and post the output in a little while.

LMHmedchem

---------- Post updated at 07:18 PM ---------- Previous update was at 03:30 PM ----------

I added the system shell line,

system("ls -l /proc/self/fd > /path/to/files.txt");

This is the output,

total 0
lrwx------ 1 lmh lmh 64 Mar 29 19:03 0 -> /dev/pts/1
l-wx------ 1 lmh lmh 64 Mar 29 19:03 1 -> /home/lmh/openstuff.txt
lrwx------ 1 lmh lmh 64 Mar 29 19:03 2 -> /dev/pts/1
lr-x------ 1 lmh lmh 64 Mar 29 19:03 3 -> /proc/22505/fd

The program arch looks like,

cpp parent process
   > fork() cpp child process
      > call to Fortran subroutine from child
         > calls to cpp fuctions from Fortran sub

The parent and child pass data through shared memory. I believe that there are pipes as well, but I don't remember.

After adding some additional print statements, I find that I am able to print from the partent process code using std::cout. I am also able to print from the child process code. I am not able to print from the Fortran sub src, or from any of the cpp functions called by the Fortran sub. All of that code is identical for both the windows and linux versions.

I don't know if this helps or not.

1 Like

Blast, that didn't do what I wanted! :wall: It redirected stdout into openstuff to save the list, so we can't see what it had before!

It should still work if we make it ls the parent instead.

Try this:

// for getpid
#include <unistd.h>

...

// Anywhere in your code
{
        char buf[128];
        sprintf(buf, "ls /proc/%d/fd > /home/lmh/openstuff.txt", (int)getpid());
        system(buf);
}

I was able to get in touch with the coder who wrote this part of the app, and he thinks that possible cout and cerr are re-directed to dev/null somewhere. This was written at least 10 years ago, so his recollections are a bit hazy. Apparently the child process runs more or less like a Daemon and things like standard streams are poorly defined.

He suggested adding a verbosity flag, and if that doesn't work, creating an fstream for debugging with a hard path, instead of using cout. Something like,

std::ofstream mycout("/tmp/mydebugfile");

None of this explains why it works in windows cygwin, except that the src for the child main function is rather different in windows as compared to linux. I tried a diff to see if I could spot the relevant difference between the src files, but they are a bit too different and the diff is pretty messy.

What should I look for in the src that would be an indication that cout is going to dev/null, or somewhere other than the terminal?

I will run the code you posted above and post back in a bit.

LMHmedchem

---------- Post updated at 01:16 PM ---------- Previous update was at 12:32 PM ----------

I put the code you posted in three places in the code, in case things changed at some point. I put it at the beginning of the parent code, and also in the child main, before and after the fortran function is called.

In all cases, it just outputs numbers, the location outputs 0, 1, and 2. The next location outputs, 0, 1, 2, 3 and 4, and the last location, 0, 1, 2, 3, 4 and 5.

That sounds quite possible.

Not really the same program at all, then. I bet that's it.

Look for close( or dup( or dup2( or freopen( or STDIN_FILENO or STDOUT_FILENO or STDERR_FILENO. Also look for /dev/null, of course.

Crap. I forgot to do ls -l instead of ls. :wall:

1 Like

Well I found it, :b:

#ifdef RELEASEVERSION
   freopen( "/dev/null", "w", stdout);
   freopen( "/dev/null", "w", stderr);
#endif

I didn't think that RELEASEVERSION was defined in the make, but commenting this out fixes the issue, so it must be. This is a sensible code addtition, since if there is an error, the child is supposed to report that back to the parent as an error code, not send it to a terminal, which may or may not exist.

I realize that this was a difficult fix without the src available, so I really appreciate all of your effort in helping me to get it sorted out.

I wish I was a good enough programmer to contribute in the same way. I do look for posts that I think I can answer, but most of the ones I find have already been attended to. I am reluctant to give advice that may be incorrect. I give allot of hardware adivce on some other forums, which is something I feel much more competent about, so I hope that I am making an overall contribution the the online world.

Thanks again,

LMHmedchem

---------- Post updated at 02:28 PM ---------- Previous update was at 02:24 PM ----------

Is there a way to mark the thread as solved, or don't they do that here?

1 Like