exec doesnt return nil

Started by newdep, May 07, 2008, 01:53:04 AM

Previous topic - Next topic

newdep

Hi Lutz,



Linux 9.3.11



-- manual --

In the first form, exec launches a process described in str-process  and

returns all standard output as an array of strings (one for each line in stdout).

exec returns nil  if the process could not be launched.

--



But in real practice, exec returns an empty list! or ERR or std-error

and does NOT return the error in an array of strings.



> (exec "ls -W")

ls: invalid option -- W

Try `ls --help' for more information.

()

>
-- (define? (Cornflakes))

Lutz

#1
The process did launch, so it returned not 'nil'. It returned an empty list, because there was no stdout for valid output, only error output. So you have three outcomes:



could not launch => nil

no stdout => ()

stdout => ("..." ...)



I think its Ok, that 'exec' does not include error output in the list. The list should only include valid output, this way you can check with 'empty?'.



ps: but is should say: list of strings, not: array of strings



corrected and expnd text here:

http://newlisp.org/download/development/newlisp_manual.html#exec">http://newlisp.org/download/development ... .html#exec">http://newlisp.org/download/development/newlisp_manual.html#exec

newdep

#2
Oke i agree that the stderr is not caught, but 'exec' will always execute

no matter what you put in it ;-) It will never return 'nil.



>(exec "tqwt134t6")

sh: command not found

()

>
-- (define? (Cornflakes))

pjot

#3
Some other thing that wonders me is the way (process) works.
Quote
peter[~]$ newlisp

newLISP v.9.3.11 on Linux IPv4, execute 'newlisp -h' for more info.



> (process "xclock")

2191

>

> (process "/usr/bin/xclock")

2208

> Warning: Missing charsets in String to FontSet conversion

Warning: Unable to load any usable fontset


In above situation, when I run 'xclock' the first time, I get a PID returned but the program does not work at all.



Only when using the full path I really see the 'xclock' program.



The manual says:
Quote
In the first syntax, process launches a process specified in str-command and immediately returns with the process ID or nil if a the process could not be created. On Mac OS X and other UNIX, the application or script must be specified with its full path-name.


Well, this is in fact not true, as I do get a PID in the first attempt when trying to run 'xclock'.



So why do we need to enter the full path? This used not be the case in previous versions of newLisp, because my programs using (process) without using the full path were working.



Peter

Lutz

#4
Quote from: "Norman"Post subject:   

Oke i agree that the stderr is not caught, but 'exec' will always execute

no matter what you put in it ;-) I


'exec' invokes the shell interpreter vi popen(), it would return 'nil' if it would fail to do this. The fact that the shell write a message to to stderr, means that it was running.



If you redirect the error message to stdout, you see what I mean:


> (exec "jhgkjhgkjhg 2>&1")
("sh: jhgkjhgkjhg: command not found")
>


Quote from: "Peter"Well, this is in fact not true, as I do get a PID in the first attempt when trying to run 'xclock'.


Before 9.2.4 'process' invoked a shell (similar to 'exec'), which could look up the program to run in the executable path. This way the full path was not necessary, but an additional process was created and returned as pid. This meant that the pid returned could never be used to kill the process created.



Today 'process' uses execve(), which overlays the fork() intiated by process, but that fork than immediately dies, if the program could not be executed (*), the pid returned is the pid of the defunct process. If the command/program could be executed this pid stays alive and indentifies the process ceeated and can be used by 'destroy' (kill). This was not possible before, where the pid returned was only the pid of the auxiliary process, but the command itself was running in a shell process.



I will this clarify in the manual.



(*) it wouldn't make sense to wait for this, because you never know when the OS scheduler will handle this. So your program somehow must find different ways to find out if the program succesfully started.

pjot

#5
OK I think I understand the mechanism. This also implies the full path of the binary to be executed.



But isn't this a little unconvenient for Unix based systems? For many binaries may be installed on different locations, for example in '/usr/bin', '/bin', '/usr/local/bin' and so on.



How to overcome this situation? It would be unconvenient to adjust a newLisp program for each different Linux/BSD/Unix version.



Peter

Lutz

#6
You could do the following to find out the correct path:


> (exec "which xclock")
("/usr/X11/bin/xclock")
>


or put it all together:


> (process (first (exec "which xclock")))
22607
> (destroy 22607)
true
>


... and the pid returned can be used in 'destroy' to shut down xclock



ps: example shown on Mac OS X, which has X-Windows built-in :)