View Full Version : question related to mac osx system and c++ script
May 20, 2012, 11:50 PM
For a few days now, I've been working on a script, written in c++, which can be executed from the terminal. Within this script, it uses a system() function to execute another c++ script. The script executed from within, sets up a socket connection to a server (which server? Can be any, i've tried several different approaches including telnet with '&').
When an ampersand is included, the script pauses at the point where it tries to connect to a server. The parent process, which i've checked for, is 'launchd'.
If the ampersand is not there, then the script executes normally and the parent process is 'the program'.
I guess I should also mention that if the script which executes the c++ program is a shell script instead, it works with '&' too, however, I'm more interested in having a c++ script. The parent process of that script inside is sh.
My only clue or hint is the 'parent process'
I'm using a mac osx 10.6 operating system, and I've tried all sorts of commands to get it to run with a '&' sign, to no avail. Could this be a security issue with macs? What am I missing?
May 20, 2012, 11:58 PM
Post your code. We can't debug descriptions.
Also, C++ isn't a scripting language, so your description is fundamentally inaccurate. Even more reason to post your actual code.
May 21, 2012, 12:03 AM
Ok I meant "program" not script. Just write system("telnet 'someserver' 'someport' &"); It's still a background process, but its paused. Try kill -cont or something rather, and it still won't bloody work. It wont work, unless you take out the '&'.
May 21, 2012, 12:17 AM
Post your complete code.
Post the shell script that works correctly with &. We need to see what works, as well as what doesn't.
The telnet command is expecting input. When you use & to put a program in background, you're running it with no input (a consequence of launching it with no stdin stream). If you're not supplying any other source of input, such as input redirection, then telnet won't get far without input.
Please describe what you expect to happen by using &.
If you're expecting to drive 'telnet' by sending it commands from your C++ program, you won't get it using system(). Look at popen() instead. Or go back to the shell script that works, or explain why it needs to be a C++ program.
May 21, 2012, 12:23 AM
So you're saying that the arguments supplied with telnet aren't going through? I'm 100% sure they are. Popen() is no different except that you can store the output of the command into a file stream, which is not something I really need.
You know what, just hang on let me double check.
May 21, 2012, 12:38 AM
Arguments are passing through, it just doesnt want to create a socket connection, I really dont know what else to say. Something is blocking it when its a background process.
May 21, 2012, 12:54 AM
So you're saying that the arguments supplied with telnet aren't going through?
No. The arguments to telnet are 'someserver' and 'someport'. I fully expect those are getting through.
I'm talking about telnet's input stream, it's stdin, from which it reads commands to be performed. Stdin is not an argument; it's inherited from the parent process, unless the shell command-line redirects it.
Once again, post the shell script that you said works.
Frankly, I don't see how this command will work:
telnet someserver someport &
and I don't see why you'd expect it to.
If I have Web Sharing on a local server, and I telnet into port 80, I should be able to manually make an HTTP request. But when I do this:
telnet myserver.local 80 &
the shell tells me:
+ Stopped telnet myserver.local 80
If I do a 'ps' I can see that telnet is stopped. Why is telnet stopped? Because it's trying to read its stdin, which is exclusively owned by the interactive shell, because I put telnet in background without redirecting its stdin. What is telnet trying to read? Commands. Why? Because that's what telnet does: it reads commands from its stdin. Read the fine man page for 'telnet'.
If I were to redirect telnet's stdin like this:
telnet myserver.local 80 <someFileOfTelnetCmds &
then the backgrounded telnet would read someFileOfTelnetCmds until EOF or until it got a fatal error of some kind.
At a minimum, I think you need to read the 'bash' man page to learn what happens when a process is backgrounded by &. It's the JOB CONTROL heading, from which I pull this fragment:
Only foreground processes are allowed to read from or
write to the terminal. Background processes which attempt to read from
(write to) the terminal are sent a SIGTTIN (SIGTTOU) signal by the ter-
minal driver, which, unless caught, suspends the process.
You may also be misunderstanding what telnet does, or what it needs in the way of input. That's why I asked you to describe what you're expecting to happen. Telnet has no input stream, and without one it won't do anything useful. So knowing what you're trying to do, and how you're trying to do it, is crucial; e.g. by feeding telnet commands on stdin or hoping they come from somewhere else.
May 21, 2012, 01:41 AM
You're doing this from within a c++ program using system()?
May 21, 2012, 02:15 AM
You're doing this from within a c++ program using system()?
No. I'm typing into a Terminal window. Not a shell script, just a plain interactive Terminal window with the bash shell. I always like to test things manually before attempting to automate them with a shell script or some other program.
May 21, 2012, 02:42 AM
Well thats the problem. I can do the exact same thing in the terminal or a bash script and achieve the same thing, try it with c++ using system() and let me know. The os will block the connection when its a background process executed from the c++ program (That's what i'm thinking, I could be wrong). I'm looking more towards daemons since the parent process happens to be launchd not sh. It's just one of those things that needs a way more in depth look at.
May 21, 2012, 07:46 PM
Well thats the problem. I can do the exact same thing in the terminal or a bash script and achieve the same thing, try it with c++ using system() and let me know.
You can do what exact same thing? Run telnet in background, and see it become a stopped process?
You started with this command, but I still don't understand what you're expecting to achieve with it:
telnet someserver someport &
To me, it seems like nonsense. It makes no more sense than this command:
Both commands have the same basic problem: they reach a point where they read from stdin, but there is no redirection of stdin, so they both end up being suspended processes (or they're terminated). Unless you take them out of background suspended state, they will wait forever, because there is no way to feed their stdin streams. And if they're terminated, then there's no suspended state to take them out of, so you're even farther away from doing anything useful.
Here's another useless command:
telnet someserver someport </dev/null
It makes about as much sense as the others, but the nonsensicality is more apparent because stdin is redirected to /dev/null.
This is what telnet someserver someport & does in isolation, from a Terminal shell, or from a shell script. I emphasize in isolation, because that's the only thing you've posted: an isolated command line.
You haven't posted your shell script, which you say works. You haven't described what you're trying to accomplish in this shell script, nor in the call to system(), so there is no way for anyone else to understand the context of that isolated command.
To me, every one of these commands behaves exactly the way I'd expect: it terminates or suspends, after making the connection. What happens next is irrelevant. In both cases, the backgrounded telnet is a useless process, because no further commands can be issued without a stream or pipe to the telnet process's stdin.
When I run this C program:
int main (int argc, const char * argv)
system( "telnet solo.local 80 &" );
I see this output, where solo.local is the name of my server, and port 80 is where it's listening:
Connected to solo.local.
Escape character is '^]'.
Connection closed by foreign host.
There is no telnet process remaining as a child of launchd. It terminated when it failed to obtain a readable stdin.
In particular, telnet made a connection (evidenced by "Connected to solo.local"). It then tried reading its stdin for commands, but since the shell that started it (the shell launched by system()) had terminated already, there was no controlling terminal on the telnet process. So with no controlling terminal (thanks to launchd), the SIGTTIN signal ends up terminating the process rather than suspending it. That termination is evidence by "Connection closed by foreign host".
The absence of a telnet process is evidenced by this command line, pasted into a Terminal window after the above program is run:
ps -alwwwx | grep telnet
If there is any process that contains the word telnet anywhere in the process name or any command-line args, it will appear in the output. The only thing that ever appears is the grep command itself. Hence, there is no telnet process.
Once again, with no commands being fed to telnet, and no way to feed it anything because it's in background, the isolated command is nonsense. It makes the connection and then terminates. I see nothing useful that can be accomplished by putting telnet in background, using either system() in a C program, or using a shell script, or using a manual Terminal command-line.
This is why I'm asking for you to describe what you're trying to accomplish, or what you expect to happen. To me, it's nonsense, or at best an incomplete description.
The os will block the connection when its a background process executed from the c++ program (That's what i'm thinking, I could be wrong).
I don't understand what you mean by "block the connection".
The telnet command runs and makes the connection (see evidence above). After that point, telnet reads stdin for commands, but there's nothing there. That's the point I've been trying to make: there's nothing to read from stdin, so at that point telnet fails. It already made the connection, but beyond that is where the whole thing becomes nonsense. If telnet has no input to read, it can't do anything else.
The only distinction is how the backgrounded telnet fails. When run at an interactive shell in Terminal, the backgrounded telnet is stopped (suspended) because there is a controlling terminal. When run via system(), there is no controlling terminal, so the backgrounded telnet is simply terminated.
I'm looking more towards daemons since the parent process happens to be launchd not sh. It's just one of those things that needs a way more in depth look at.
Launchd is just the parent process of last resort. It inherits the telnet child process when the shell that launched it dies. "Looking more towards daemons" makes no sense to me.