in reply to main script invoked twice

Try setting $|=1;.

My guess is that somewhere inside of Our::UI::CommandLine there is a fork call. For details, look at perldoc -f fork, but the basic idea is that your print statement just moves that text into a buffer, not directly into the file log file your redirecting from stdout... when that fork happens, the buffer is copied to the child process, and so later on both the parent of the fork and the child of the fork flush the buffer, and whatever was in the buffer at the time of fork gets flushed twice.

------------ :Wq Not an editor command: Wq

Replies are listed 'Best First'.
Re: Re: main script invoked twice
by steves (Curate) on Mar 29, 2004 at 00:24 UTC

    But fork would yield a different process ID. It's not running long enough for PIDs to wrap and the PID is always the same. But I think the exec hint holds water. I know we have at least one piece of code that calls exec to re-start the program after setting environment variables that need to be set before shared libraries are loaded. I bet that's it ... and that would explain why it only happens from cron: those environment variables are normally set in user shells.

      Read etcshadow's reply again. And try his suggestion. If it works, then the child's pid is irrelevant; you have a buffering problem. When running under cron, you'll be sending the output to a pipe, which may buffer more than sending it to a tty.

      If setting $|=1 fixes the problem but you don't want to disable buffering, use { local $| = 1 } (including the curlies) to force a flush at the appropriate point -- probably just before the fork. ($|=1;$|=0 would do the same thing but wouldn't restore the buffering status, which is an unfriendly thing to do, especially if you're mixing in anyone else's code.)

      Yes, fork would yield a different process ID, but that doesn't matter... the child would not be re-executing the print $$;... there is hidden behavior (called buffering) underlying the standard print operation which causes something more analogous (not exacly the same) to this:
      print "PID is $$"; fork(); ... # that is (or can be) essentially the same as: $buffer = ">> PID is $$"; fork(); print $buffer;
      so the both the parent and the child process are printing the value as it was computed in the parent process.

      Get it?

      Anyway, after looking at what you just had to say about the script re-exec'ing itself, it seems obvious that what is happening is not caused by the phenomenon I was describing (the pid getting caught in the output buffer at time of fork and thereby getting printed twice). The problem is that you are exec'ing the same script again from within the same process (so it's the same pid, even though it's a fresh run of the program).

      Understand how exec works: it replaces the contents of the current process with a new program... but it retains the same process (hence the same pid). Exec is, essentially, loading the new program into the current process's memory and calling goto(begin). Now, that means that if you exec the same program that you call you exec from, then it's essentially just pressing the reset-button on your program (but, again, from within the same process, hence the same pid).

      Hope that helps.

      ------------ :Wq Not an editor command: Wq