PDA

View Full Version : fork() and execv() from a Carbon app




idelovski
Mar 26, 2013, 07:16 PM
As I run a command line tool from my Carbon application, I always have this message in (console) logs: "No such file or directory".

The cli application actually runs and does what it's supposed to do, but I still don't know why I'm getting "No such file or directory".

Carbon app is universial, ppc and i386, SDK 10.4 in Xcode 3.2.6. The command line tool is intel only. It is a Foundation tool and it's a ObjC/C combo, SDK 10.6 and has dependencies on few MacPorts libraries. If those libraries/frameworks are not present on the machine, in opt/local then in fact the tool failes to run.

How can I avoid this message and how can I test if the tool did run?

if ((processId = fork()) == 0) {
char *argv[paramCnt+2];

argv[0] = appPathName;

for (i=0; allParams[i] && i<paramCnt; i++) {
argv[i+1] = allParams[i];
}
argv[i+1] = NULL;

if (execv(appPathName, argv) < 0) {
perror ("execv error");
}
}
else if (processId < 0) {
perror("fork error");
}
else {
return (0);
}



gnasher729
Mar 26, 2013, 08:16 PM
The console should tell you which process produced that error message.

I tend to use popen; it lets you read the output of the tool quite easily and reports the exit status and whether the tool was actually run.

idelovski
Mar 26, 2013, 08:33 PM
Deliberately sent wrong args to provoke some output - Bouquet is the host app:

[..].hr.delovski.bouquet[9676] /Users/idelovski/Desktop/TestTool/build/Debug/XmlSignTest: No such file or directory
[..].hr.delovski.bouquet[9676] Error: '/Users/idelovski/Desktop/TestTool/build/Debug/XmlSignTest'
[..].hr.delovski.bouquet[9676] Error: wrong number of arguments.

And this is what I have in the cli tool in case of wrong args:

fprintf (stderr, "Error: '%s'\n", argv[0]);
fprintf (stderr, "Error: wrong number of arguments.\n");


The string "No such file or directory" is not present in my code, not in host and not in cli part.

cqexbesd
Mar 27, 2013, 06:43 AM
The string "No such file or directory" is not present in my code, not in host and not in cli part.

"No such file or directory" will be coming from perror I would guess (or similar functions that deal with errno such as strerror and warn).

The perror() function finds the error message corresponding to the current value of the global variable errno (intro(2)) and
writes it, followed by a newline, to the standard error file descriptor.

An errno value of 2 (ENOENT) will be mapped to "No such file or directory".

Have you considered either attaching to your child with a debugger and stepping through or at least putting some logging in there?

Andrew

gnasher729
Mar 27, 2013, 08:02 AM
"No such file or directory" will be coming from perror I would guess (or similar functions that deal with errno such as strerror and warn).



An errno value of 2 (ENOENT) will be mapped to "No such file or directory".

Have you considered either attaching to your child with a debugger and stepping through or at least putting some logging in there?

Andrew

More easily, instead of forking, just dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, ^ {/* your code */));

idelovski
Mar 27, 2013, 06:05 PM
"No such file or directory" will be coming from perror I would guess (or similar functions that deal with errno such as strerror and warn).

...

Andrew

Thanks. (Someone should slap me for this)

Turns out this line:

perror ("One_Two_Three");

would produce in console: One_Two_Three: No such file or directory.

At least in my case. I had perror() call in the function that was constructing full path name. Seemed as a nice way to report the result and then I forgot about it.

cqexbesd
Mar 28, 2013, 06:22 AM
More easily, instead of forking, just dispatch_async (dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, ^ {/* your code */));

Except that the OP was later calling exec and IIUC dispatch_async just potentially runs something on another thread. posix_spawn would possibly be an alternative should one be needed.

Andrew

gnasher729
Mar 28, 2013, 08:54 AM
Except that the OP was later calling exec and IIUC dispatch_async just potentially runs something on another thread. posix_spawn would possibly be an alternative should one be needed.

Andrew

Well, the question is: Why is that fork call there in the first place? It creates a second process, which calls the shell to execute a command, and nothing else. Why would you do that in a separate process? I suspect this is copied from some sample code, and the sample code did it because that way the main thread of the original process doesn't have to wait for the shell to finish.

Using GCD to do it on a background thread is much cheaper, much easier, and makes debugging a lot easier.

cqexbesd
Mar 28, 2013, 10:17 AM
Well, the question is: Why is that fork call there in the first place? It creates a second process, which calls the shell to execute a command, and nothing else. Why would you do that in a separate process?

The code doesn't actually call the shell - but maybe that isn't what you actually meant.

If there is an existing program that does what you want then you may as well use it rather than reinventing the wheel. I'm not suggesting you should always use an external command of course but there are plenty of legitimate reasons to do so. Once you have decided you want to use another tool you have little choice but to fork (or as I said earlier posix_spawn) in some guise or other.

Using GCD to do it on a background thread is much cheaper, much easier, and makes debugging a lot easier.

Using another thread rather than another process has a lot of different semantics however. To say it is cheaper, easier and easier to debug depends so very much on the exact problem at hand and I don't think we have enough details to make that call. Only the OP knows their exact requirements and so can make the usually subjective decision as to which to use and they appear to have gone for fork/exec. They are using Carbon so I imagine there are under a number of constraints they haven't mentioned.

Andrew