Skip to content
This repository has been archived by the owner on Nov 7, 2019. It is now read-only.

Commit

Permalink
1633 implement posix_spawn_pipe_np()
Browse files Browse the repository at this point in the history
Reviewed by: Adam Leventhal <Adam.Leventhal@delphix.com>
Reviewed by: Eric Schrock <Eric.Schrock@delphix.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Approved by: Eric Schrock <Eric.Schrock@delphix.com>
  • Loading branch information
ahrens committed Oct 18, 2011
1 parent 9729663 commit 462453d
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 60 deletions.
13 changes: 13 additions & 0 deletions usr/src/head/spawn.h
Expand Up @@ -24,6 +24,10 @@
* Use is subject to license terms.
*/

/*
* Copyright (c) 2011 by Delphix. All rights reserved.
*/

#ifndef _SPAWN_H
#define _SPAWN_H

Expand Down Expand Up @@ -154,6 +158,14 @@ extern int posix_spawnattr_getsigdefault(
*/
#if !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)

extern int posix_spawn_pipe_np(
pid_t *_RESTRICT_KYWD pidp,
int *_RESTRICT_KYWD fdp,
const char *_RESTRICT_KYWD cmd,
boolean_t write,
posix_spawn_file_actions_t *_RESTRICT_KYWD fact,
posix_spawnattr_t *_RESTRICT_KYWD attr);

extern int posix_spawn_file_actions_addclosefrom_np(
posix_spawn_file_actions_t *file_actions,
int lowfiledes);
Expand Down Expand Up @@ -198,6 +210,7 @@ extern int posix_spawnattr_getschedpolicy();
extern int posix_spawnattr_setsigdefault();
extern int posix_spawnattr_getsigdefault();
#if !defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)
extern int posix_spawn_pipe_np();
extern int posix_spawn_file_actions_addclosefrom_np();
extern int posix_spawnattr_setsigignore_np();
extern int posix_spawnattr_getsigignore_np();
Expand Down
7 changes: 7 additions & 0 deletions usr/src/lib/libc/port/mapfile-vers
Expand Up @@ -24,6 +24,8 @@
# Copyright 2010 Nexenta Systems, Inc. All rights reserved.
# Use is subject to license terms.
#
# Copyright (c) 2011 by Delphix. All rights reserved.
#

#
# MAPFILE HEADER START
Expand Down Expand Up @@ -88,6 +90,11 @@ $if _x86 && _ELF64
$add amd64
$endif

SYMBOL_VERSION ILLUMOS_0.2 { # Illumos additions
protected:
posix_spawn_pipe_np;
} ILLUMOS_0.1;

SYMBOL_VERSION ILLUMOS_0.1 { # Illumos additions
protected:
timegm;
Expand Down
99 changes: 42 additions & 57 deletions usr/src/lib/libc/port/stdio/popen.c
Expand Up @@ -24,6 +24,10 @@
* Use is subject to license terms.
*/

/*
* Copyright (c) 2011 by Delphix. All rights reserved.
*/

/* Copyright (c) 1988 AT&T */
/* All Rights Reserved */

Expand All @@ -50,13 +54,6 @@
#include "mse.h"
#include "libc.h"

#define tst(a, b) (*mode == 'r'? (b) : (a))
#define RDR 0
#define WTR 1

extern int __xpg4; /* defined in _xpg4.c; 0 if not xpg4-compiled program */
extern const char **_environ;

static mutex_t popen_lock = DEFAULTMUTEX;

typedef struct node {
Expand Down Expand Up @@ -91,22 +88,15 @@ cleanup(void *arg)
FILE *
popen(const char *cmd, const char *mode)
{
int p[2];
pid_t pid;
int myside;
int yourside;
int fd;
int myfd, fd;
const char *shpath = _PATH_BSHELL;
FILE *iop;
int stdio;
node_t *curr;
char *argvec[4];
node_t *node;
posix_spawnattr_t attr;
posix_spawn_file_actions_t fact;
posix_spawnattr_t attr;
int error;
static const char *shell = "sh";
static const char *sh_flg = "-c";

if ((node = lmalloc(sizeof (node_t))) == NULL)
return (NULL);
Expand All @@ -121,31 +111,33 @@ popen(const char *cmd, const char *mode)
errno = error;
return (NULL);
}
if (pipe(p) < 0) {

if (access(shpath, X_OK)) /* XPG4 Requirement: */
shpath = ""; /* force child to fail immediately */


/*
* fdopen() can fail (if the fd is too high or we are out of memory),
* but we don't want to have any way to fail after creating the child
* process. So we fdopen() a dummy fd (myfd), and once we get the real
* fd from posix_spawn_pipe_np(), we dup2() the real fd onto the dummy.
*/
myfd = open("/dev/null", O_RDWR);
if (myfd == -1) {
error = errno;
lfree(node, sizeof (node_t));
(void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
errno = error;
return (NULL);
}

if (access(shpath, X_OK)) /* XPG4 Requirement: */
shpath = ""; /* force child to fail immediately */

myside = tst(p[WTR], p[RDR]);
yourside = tst(p[RDR], p[WTR]);
/* myside and yourside reverse roles in child */
stdio = tst(0, 1);

/* This will fail more quickly if we run out of fds */
if ((iop = fdopen(myside, mode)) == NULL) {
iop = fdopen(myfd, mode);
if (iop == NULL) {
error = errno;
lfree(node, sizeof (node_t));
(void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
(void) close(yourside);
(void) close(myside);
(void) close(myfd);
errno = error;
return (NULL);
}
Expand All @@ -155,64 +147,57 @@ popen(const char *cmd, const char *mode)
/* in the child, close all pipes from other popen's */
for (curr = head; curr != NULL && error == 0; curr = curr->next) {
/*
* These conditions may apply if a previous iob returned
* The fd may no longer be open if an iob previously returned
* by popen() was closed with fclose() rather than pclose(),
* or if close(fileno(iob)) was called. Don't let these
* programming errors cause us to malfunction here.
* or if close(fileno(iob)) was called. Use fcntl() to check
* if the fd is still open, so that these programming errors
* won't cause us to malfunction here.
*/
if ((fd = curr->fd) != myside && fd != yourside &&
fcntl(fd, F_GETFD) >= 0)
error = posix_spawn_file_actions_addclose(&fact, fd);
}
if (error == 0)
error = posix_spawn_file_actions_addclose(&fact, myside);
if (yourside != stdio) {
if (error == 0)
error = posix_spawn_file_actions_adddup2(&fact,
yourside, stdio);
if (error == 0)
if (fcntl(curr->fd, F_GETFD) >= 0) {
error = posix_spawn_file_actions_addclose(&fact,
yourside);
curr->fd);
}
}
/*
* See the comments in port/stdio/system.c for why these
* non-portable posix_spawn() attributes are being used.
*/
if (error == 0)
if (error == 0) {
error = posix_spawnattr_setflags(&attr,
POSIX_SPAWN_NOSIGCHLD_NP |
POSIX_SPAWN_WAITPID_NP |
POSIX_SPAWN_NOEXECERR_NP);
if (error) {
}
if (error != 0) {
lmutex_unlock(&popen_lock);
lfree(node, sizeof (node_t));
(void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
(void) fclose(iop);
(void) close(yourside);
errno = error;
return (NULL);
}
argvec[0] = (char *)shell;
argvec[1] = (char *)sh_flg;
argvec[2] = (char *)cmd;
argvec[3] = NULL;
error = posix_spawn(&pid, shpath, &fact, &attr,
(char *const *)argvec, (char *const *)_environ);
error = posix_spawn_pipe_np(&pid, &fd, cmd, *mode != 'r', &fact, &attr);
(void) posix_spawnattr_destroy(&attr);
(void) posix_spawn_file_actions_destroy(&fact);
(void) close(yourside);
if (error) {
if (error != 0) {
lmutex_unlock(&popen_lock);
lfree(node, sizeof (node_t));
(void) fclose(iop);
errno = error;
return (NULL);
}
_insert_nolock(pid, myside, node);
_insert_nolock(pid, myfd, node);

lmutex_unlock(&popen_lock);

/*
* myfd is the one that we fdopen()'ed; make it refer to the
* pipe to the child.
*/
(void) dup2(fd, myfd);
(void) close(fd);

_SET_ORIENTATION_BYTE(iop);

return (iop);
Expand Down
70 changes: 70 additions & 0 deletions usr/src/lib/libc/port/threads/spawn.c
Expand Up @@ -24,6 +24,10 @@
* Use is subject to license terms.
*/

/*
* Copyright (c) 2011 by Delphix. All rights reserved.
*/

#include "lint.h"
#include "thr_uberdata.h"
#include <sys/libc_kernel.h>
Expand Down Expand Up @@ -77,6 +81,8 @@ typedef struct file_attr {
extern int getdents64(int, dirent64_t *, size_t);
#endif

extern const char **_environ;

/*
* Support function:
* Close all open file descriptors greater than or equal to lowfd.
Expand Down Expand Up @@ -879,3 +885,67 @@ posix_spawnattr_getsigmask(
*sigmask = sap->sa_sigmask;
return (0);
}

/*
* Spawn a process to run "sh -c <cmd>". Return the child's pid (in
* *pidp), and a file descriptor (in *fdp) for reading or writing to the
* child process, depending on the 'write' argument.
* Return 0 on success; otherwise return an error code.
*/
int
posix_spawn_pipe_np(pid_t *pidp, int *fdp,
const char *cmd, boolean_t write,
posix_spawn_file_actions_t *fact, posix_spawnattr_t *attr)
{
int p[2];
int myside, yourside, stdio;
const char *shpath = _PATH_BSHELL;
const char *argvec[4] = { "sh", "-c", cmd, NULL };
int error;

if (pipe(p) < 0)
return (errno);

if (access(shpath, X_OK)) /* XPG4 Requirement: */
shpath = ""; /* force child to fail immediately */

if (write) {
/*
* Data is read from p[0] and written to p[1].
* 'stdio' is the fd in the child process that should be
* connected to the pipe.
*/
myside = p[1];
yourside = p[0];
stdio = STDIN_FILENO;
} else {
myside = p[0];
yourside = p[1];
stdio = STDOUT_FILENO;
}

error = posix_spawn_file_actions_addclose(fact, myside);
if (yourside != stdio) {
if (error == 0) {
error = posix_spawn_file_actions_adddup2(fact,
yourside, stdio);
}
if (error == 0) {
error = posix_spawn_file_actions_addclose(fact,
yourside);
}
}

if (error)
return (error);
error = posix_spawn(pidp, shpath, fact, attr,
(char *const *)argvec, (char *const *)_environ);
(void) close(yourside);
if (error) {
(void) close(myside);
return (error);
}

*fdp = myside;
return (0);
}
1 change: 1 addition & 0 deletions usr/src/man/man3c/Makefile
Expand Up @@ -256,6 +256,7 @@ MANFILES = __fbufsize.3c \
posix_spawn_file_actions_addclosefrom_np.3c \
posix_spawn_file_actions_adddup2.3c \
posix_spawn_file_actions_destroy.3c \
posix_spawn_pipe_np.3c \
posix_spawnattr_destroy.3c \
posix_spawnattr_getflags.3c \
posix_spawnattr_getpgroup.3c \
Expand Down
5 changes: 4 additions & 1 deletion usr/src/man/man3c/posix_spawn.3c
Expand Up @@ -9,6 +9,7 @@
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
.\" Copyright 2011 by Delphix. All rights reserved.
.TH POSIX_SPAWN 3C "Feb 20, 2009"
.SH NAME
posix_spawn, posix_spawnp \- spawn a process
Expand Down Expand Up @@ -388,7 +389,9 @@ Standard See \fBstandards\fR(5).
\fBposix_spawn_file_actions_adddup2\fR(3C),
\fBposix_spawn_file_actions_addopen\fR(3C),
\fBposix_spawn_file_actions_destroy\fR(3C),
\fBposix_spawn_file_actions_init\fR(3C), \fBposix_spawnattr_destroy\fR(3C),
\fBposix_spawn_file_actions_init\fR(3C),
\fBposix_spawn_pipe_np\fR(3C),
\fBposix_spawnattr_destroy\fR(3C),
\fBposix_spawnattr_getflags\fR(3C), \fBposix_spawnattr_getpgroup\fR(3C),
\fBposix_spawnattr_getschedparam\fR(3C),
\fBposix_spawnattr_getschedpolicy\fR(3C),
Expand Down

0 comments on commit 462453d

Please sign in to comment.