Hello, a dash script like: date > foobar.txt date is (as an SSCCE) handled like this: int fd; int saved; fd = open64("foobar.txt", O_WRONLY|O_CREAT); saved = fcntl(1, F_DUPFD, 10); dup2(fd, 1); if (!fork()) { execl("/bin/date", "date", (char *)NULL); } dup2(saved, 1); if (!fork()) { execl("/bin/date", "date", (char *)NULL); } This is strange. Why save, dup and dup again to restore, descriptors in the parent, when it would be much simpler to just dup in the child, and not have to save and restore. This is simpler and I checked it works the same: int fd; if (!fork()) { fd = open64("foobar.txt", O_WRONLY|O_CREAT); dup2(fd, 1); execl("/bin/date", "date", (char *)NULL); } if (!fork()) { execl("/bin/date", "date", (char *)NULL); } I am sure there must be a good reason and I am not understanding something deeper. What is it? Thank you, Mark
On 31/01/2017 21:00, Mark Galeck wrote:
> Why save, dup and dup again to restore, descriptors in the parent, when it would be much simpler to just dup in the child, and not have to save and restore.
This assumes there's a child in the first place. Depending on the
command, that might not be the case, think of built-in commands such as
echo for instance. Code is needed to handle that case, and I suspect
that if that code is there anyway, then having one place to set up
redirections is simpler than having two places to set up redirections.
Cheers,
Harald van Dijk
On Tue, Jan 31, 2017 at 12:00 PM, Mark Galeck <mark_galeck@pacbell.net> wrote: > This is strange. Why save, dup and dup again to restore, descriptors in the parent, when it would be much simpler to just dup in the child, and not have to save and restore. This is simpler and I checked it works the same: > I am sure there must be a good reason and I am not understanding something deeper. What is it? I am not a dash developer, but one reason to make system calls in the parent is that it is much simpler to handle errors in the parent. In your example: > if (!fork()) { > fd = open64("foobar.txt", O_WRONLY|O_CREAT); > dup2(fd, 1); > execl("/bin/date", "date", (char *)NULL); > } What happens if open64 fails? How should the child inform the parent of this specific error? -Parke
Thank you Harald and Parke for your very informative comments, I appreciate! Mark
On Tue, Jan 31, 2017 at 06:27:00PM -0800, Parke wrote: > On Tue, Jan 31, 2017 at 12:00 PM, Mark Galeck <mark_galeck@pacbell.net> wrote: > > This is strange. Why save, dup and dup again to restore, descriptors > > in the parent, when it would be much simpler to just dup in the > > child, and not have to save and restore. This is simpler and I > > checked it works the same: > > I am sure there must be a good reason and I am not understanding > > something deeper. What is it? > I am not a dash developer, but one reason to make system calls in the > parent is that it is much simpler to handle errors in the parent. > In your example: > > if (!fork()) { > > fd = open64("foobar.txt", O_WRONLY|O_CREAT); > > dup2(fd, 1); > > execl("/bin/date", "date", (char *)NULL); > > } > What happens if open64 fails? How should the child inform the parent > of this specific error? In general, you are right, but in the shell's case there is no difficulty. The error is reported via an error message to stderr and a non-zero exit status of the command, and the child process can easily do those things. -- Jilles Tjoelker