From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-3.9 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.1 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 9B6081F85B for ; Tue, 26 Jun 2018 09:38:19 +0000 (UTC) From: Eric Wong To: spew@80x24.org Subject: [PATCH 10/14] grantpt Date: Tue, 26 Jun 2018 09:38:13 +0000 Message-Id: <20180626093817.1533-11-e@80x24.org> In-Reply-To: <20180626093817.1533-1-e@80x24.org> References: <20180626093817.1533-1-e@80x24.org> List-Id: --- configure.ac | 1 + ext/pty/pty.c | 22 ++++------------------ internal.h | 3 +++ signal.c | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/configure.ac b/configure.ac index d9283d9e17..f48db0733c 100644 --- a/configure.ac +++ b/configure.ac @@ -1782,6 +1782,7 @@ AC_CHECK_FUNCS(getsid) AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday AC_CHECK_FUNCS(getuidx) AC_CHECK_FUNCS(gmtime_r) +AC_CHECK_FUNCS(grantpt) AC_CHECK_FUNCS(initgroups) AC_CHECK_FUNCS(ioctl) AC_CHECK_FUNCS(isfinite) diff --git a/ext/pty/pty.c b/ext/pty/pty.c index b3c7535321..1ac89061c1 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -246,19 +246,13 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, /* Unix98 PTY */ int masterfd = -1, slavefd = -1; char *slavedevice; - struct sigaction dfl, old; - - dfl.sa_handler = SIG_DFL; - dfl.sa_flags = 0; - sigemptyset(&dfl.sa_mask); #if defined(__sun) || (defined(__FreeBSD__) && __FreeBSD_version < 902000) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ /* FreeBSD 9.2 or later supports O_CLOEXEC * http://www.freebsd.org/cgi/query-pr.cgi?pr=162374 */ if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1) goto error; - if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; - if (grantpt(masterfd) == -1) goto grantpt_error; + if (rb_grantpt(masterfd) == -1) goto error; rb_fd_fix_cloexec(masterfd); #else { @@ -272,10 +266,8 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if ((masterfd = posix_openpt(flags)) == -1) goto error; } rb_fd_fix_cloexec(masterfd); - if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; - if (grantpt(masterfd) == -1) goto grantpt_error; + if (rb_grantpt(masterfd) == -1) goto error; #endif - if (sigaction(SIGCHLD, &old, NULL) == -1) goto error; if (unlockpt(masterfd) == -1) goto error; if ((slavedevice = ptsname(masterfd)) == NULL) goto error; if (no_mesg(slavedevice, nomesg) == -1) goto error; @@ -293,8 +285,6 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; - grantpt_error: - sigaction(SIGCHLD, &old, NULL); error: if (slavefd != -1) close(slavefd); if (masterfd != -1) close(masterfd); @@ -346,21 +336,17 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, extern char *ptsname(int); extern int unlockpt(int); - extern int grantpt(int); #if defined(__sun) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ if((masterfd = open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; - s = signal(SIGCHLD, SIG_DFL); - if(grantpt(masterfd) == -1) goto error; + if(rb_grantpt(masterfd) == -1) goto error; rb_fd_fix_cloexec(masterfd); #else if((masterfd = rb_cloexec_open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; rb_update_max_fd(masterfd); - s = signal(SIGCHLD, SIG_DFL); - if(grantpt(masterfd) == -1) goto error; + if(rb_grantpt(masterfd) == -1) goto error; #endif - signal(SIGCHLD, s); if(unlockpt(masterfd) == -1) goto error; if((slavedevice = ptsname(masterfd)) == NULL) goto error; if (no_mesg(slavedevice, nomesg) == -1) goto error; diff --git a/internal.h b/internal.h index c486a46d99..4cd1e7b181 100644 --- a/internal.h +++ b/internal.h @@ -2039,6 +2039,9 @@ VALUE rb_gcd_normal(VALUE self, VALUE other); VALUE rb_gcd_gmp(VALUE x, VALUE y); #endif +/* signal.c (export) */ +int rb_grantpt(int fd); + /* string.c (export) */ #ifdef RUBY_ENCODING_H /* internal use */ diff --git a/signal.c b/signal.c index 9f74c43c5d..d09480fb6f 100644 --- a/signal.c +++ b/signal.c @@ -1573,3 +1573,43 @@ Init_signal(void) rb_enable_interrupt(); } + +#if defined(HAVE_GRANTPT) +extern int grantpt(int); +#endif + +int +rb_grantpt(int masterfd) +{ + int ret = -1; + int e = ENOSYS; +#if defined(HAVE_GRANTPT) + if (RUBY_SIGCHLD) { + rb_vm_t *vm = GET_VM(); + + rb_nativethread_lock_lock(&vm->waitpid_lock); + if (list_empty(&vm->waiting_pids) && list_empty(&vm->waiting_grps)) { + sighandler_t old = ruby_signal(RUBY_SIGCHLD, SIG_DFL); + + ret = grantpt(masterfd); + if (ret < 0) e = errno; + + ruby_signal(RUBY_SIGCHLD, old); + } + else { + /* grantpt cannot function with multiple threads in waitpid */ + e = EAGAIN; + ret = -1; + } + rb_nativethread_lock_unlock(&vm->waitpid_lock); + } + else { + /* maybe some platforms have grantpt w/o SIGCHLD */ + return grantpt(masterfd); + } +#endif /* !HAVE_GRANTPT */ + + if (ret < 0) + errno = e; + return ret; +} -- EW