views:

148

answers:

5

I have a C++ windows service that sometimes crashes when I call the system() function to shell out a command. I've run the exact text of the command in the windows command-line, and it runs just fine, but for some reason it fails when system() is run.

To make matters worse, I can't seem to get any information as to why system() is failing. There doesn't seem to be an exception raised, because I'm doing a catch(...) and nothing's getting caught. My service just stops running. I know that it's the call to system() that is failing because I've put logging information before and after the call, and anything after just doesn't log anything.

So, is there a different way that I can shell out my command? At the very least, something that will give me some information if things go wrong, or at least let me handle an exception or something.

A: 

You could use fork/exec, but I think that is what the system is doing.

VJo
`exec` will definitely give you more control of the process. Many systems also have the `spawn` function.
Ben Voigt
Unlikely, given that it's Windows. More likely to be CreateProcess or similar.
SimonJ
Fork doesn't exist in the Windows API.
OJ
The question before editing was not windows specific, hence the answer.
VJo
+1  A: 

I belive system() is technically part of the C standard library, and therefore wouldn't throw exceptions. You should be able to check the return code or the ERRNO variable to get some information about what happened. This MSDN link has some information about the possible return codes on Windows.

I've also seen system() fail for other external reasons, such as virus scanners, so you might investigate that as well.

I don't know of a better way to run shell commands, but I could be wrong.

EDIT: If it still just seems to crash for no reason, you might try using process monitor to see what is going on at a lower level. Since the output from process monitor can be kind of overwhelming, a trick I like to use is to add a statement right before the call to system() to your program to open a nonexistent file like "C:\MARKER.TXT" or something, then you can search the process monitor output for the name of the file and look at the entries right afterward that may have something to do with the problem.

bde
The thing is, my app seems to just die when system is called. I try to log something immediately after I call system, but I get nothing.
Mike Pateras
Are you sure the string you pass to `system()` actually contains what you want? As a test, you could try to run `system()` with a different command, like `sleep` or something, and see if that works.
bde
Run system("dir") and see if you get something
VJo
Yes, I"m sure. It's only with some commands that system fails, and I've printed them out to my log file. I know which commands fail, and as I said, I've run that very same command in the command line, and it works just fine.
Mike Pateras
In that case, I'd recommend using process monitor to try to get some more clues. I edited my answer to include a link.
bde
+1  A: 

Ordinary catch() will not catch fatal exceptions (e.g. segmentation fault). You have to use structured exception handling. Better yet, enable post-mortem debugging; this article explains how you can enable post-mortem debugging of services.

zvrba
A: 

I think your problem could be the user account associated on your service.

Either there's an environment problem (missing entry in path) or the account the service is using to run doesn't have the rights to exec whatever you're trying to run.

Run services.msc and look at the properties for your service. On the logon page, as a test, change the setup so it uses your account to run the service. If it succeeds, you know what the problem is.

Another thing to look at is the path while inside the service. Use getenv( "PATH" ) and see if a path you might be reliant on is missing.

Hope this helps...

JimR
A: 

I ended up using CreateProcess. It's been working out so far.

Mike Pateras