Hi,
At Mon, 6 Aug 2007 02:28:38 +0900,
ronald braswell wrote in [ruby-talk:263410]:
I noticed that Solaris 10 does not support TIOCSCTTY so in function
establishShell() the child process closes the slave device and reopens it to
force it to be the controlling tty. The parent process also closes the
slave device because it does not need it. I added a call to nanosleep for
20 milliseconds just before the parent process closes the slave fd at the
end of establishShell() and I now both expect and RExpect work reliably. I
suspect that just keeping a reference to the open file object in the parent
process while the child process closes and reopens the slave device prevents
the EOF from occurring -- but I am far from an expert on Solaris internals.
This may not be the best way to solve the problem and just adding the small
delay does not ensure that the problem will never happen again but so far,
so good.
Does this patch work?
Index: ext/pty/expect_sample.rb
===================================================================
--- ext/pty/expect_sample.rb (revision 12878)
+++ ext/pty/expect_sample.rb (working copy)
@@ -16,8 +16,4 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r
$expect_verbose = false
- r_f.expect(/^Name.*: /) do
- w_f.print "ftp\n"
- end
-
if !ENV['USER'].nil?
username = ENV['USER']
@@ -28,9 +24,6 @@ PTY.spawn("ftp ftp.ruby-lang.org") do |r
end
- r_f.expect('word:') do
- w_f.print username+"@\n"
- end
- r_f.expect("> ") do
- w_f.print "cd pub/ruby\n"
+ r_f.expect(/^(Name).*: |(word):|> /) do
+ w_f.puts($1 ? "ftp" : $2 ? "#{username}@" : "cd pub/ruby")
end
r_f.expect("> ") do
Index: ext/pty/pty.c
===================================================================
--- ext/pty/pty.c (revision 12878)
+++ ext/pty/pty.c (working copy)
@@ -40,8 +40,8 @@
#if !defined(HAVE_OPENPTY)
#if defined(__hpux)
-static
-char *MasterDevice = "/dev/ptym/pty%s",
- *SlaveDevice = "/dev/pty/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptym/pty%s",
+ SlaveDevice[] = "/dev/pty/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
@@ -63,8 +63,8 @@ char *MasterDevice = "/dev/ptym/pty%s",
};
#elif defined(_IBMESA) /* AIX/ESA */
-static
-char *MasterDevice = "/dev/ptyp%s",
- *SlaveDevice = "/dev/ttyp%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/ptyp%s",
+ SlaveDevice[] = "/dev/ttyp%s",
+ *const deviceNo[] = {
"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
@@ -85,8 +85,8 @@ char *MasterDevice = "/dev/ptyp%s",
};
#elif !defined(HAVE_PTSNAME)
-static
-char *MasterDevice = "/dev/pty%s",
- *SlaveDevice = "/dev/tty%s",
- *deviceNo[] = {
+static const
+char MasterDevice[] = "/dev/pty%s",
+ SlaveDevice[] = "/dev/tty%s",
+ *const deviceNo[] = {
"p0","p1","p2","p3","p4","p5","p6","p7",
"p8","p9","pa","pb","pc","pd","pe","pf",
@@ -102,6 +102,4 @@ char *MasterDevice = "/dev/pty%s",
#endif /* !defined(HAVE_OPENPTY) */
-static char SlaveName[DEVICELEN];
-
#ifndef HAVE_SETEUID
# ifdef HAVE_SETREUID
@@ -156,15 +154,13 @@ pty_syswait(info)
if (cpid == -1) return Qnil;
-#if defined(IF_STOPPED)
- if (IF_STOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
-#elif defined(WIFSTOPPED)
- if (WIFSTOPPED(status)) { /* suspend */
- raise_from_wait("stopped", info);
- }
+#if defined(WIFSTOPPED)
+#elif defined(IF_STOPPED)
+#define WIFSTOPPED(status) IF_STOPPED(status)
#else
---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
#endif /* WIFSTOPPED | IF_STOPPED */
+ if (WIFSTOPPED(status)) { /* suspend */
+ raise_from_wait("stopped", info);
+ }
else if (kill(info->child_pid, 0) == 0) {
raise_from_wait("changed", info);
@@ -177,5 +173,5 @@ pty_syswait(info)
}
-static void getDevice _((int*, int*));
+static void getDevice _((int*, int*, char [DEVICELEN]));
struct exec_info {
@@ -195,11 +191,12 @@ pty_exec(v)
static void
-establishShell(argc, argv, info)
+establishShell(argc, argv, info, SlaveName)
int argc;
VALUE *argv;
struct pty_info *info;
+ char SlaveName[DEVICELEN];
{
int i,master,slave;
- char *p,*getenv();
+ char *p, tmp, *getenv();
struct passwd *pwent;
VALUE v;
@@ -224,5 +221,5 @@ establishShell(argc, argv, info)
argv = &v;
}
- getDevice(&master,&slave);
+ getDevice(&master, &slave, SlaveName);
info->thread = rb_thread_current();
@@ -274,4 +271,5 @@ establishShell(argc, argv, info)
close(master);
#endif
+ write(slave, "", 1);
dup2(slave,0);
dup2(slave,1);
@@ -289,4 +287,5 @@ establishShell(argc, argv, info)
}
+ read(master, &tmp, 1);
close(slave);
@@ -306,6 +305,7 @@ pty_finalize_syswait(info)
static int
-get_device_once(master, slave, fail)
+get_device_once(master, slave, SlaveName, fail)
int *master, *slave, fail;
+ char SlaveName[DEVICELEN];
{
#if defined HAVE_OPENPTY
@@ -354,4 +354,5 @@ get_device_once(master, slave, fail)
if(ioctl(j, I_PUSH, "ptem") != -1) {
if(ioctl(j, I_PUSH, "ldterm") != -1) {
+ ioctl(j, I_PUSH, "ttcompat");
#endif
*master = i;
@@ -396,10 +397,11 @@ get_device_once(master, slave, fail)
static void
-getDevice(master, slave)
+getDevice(master, slave, SlaveName)
int *master, *slave;
+ char SlaveName[DEVICELEN];
{
- if (get_device_once(master, slave, 0)) {
+ if (get_device_once(master, slave, SlaveName, 0)) {
rb_gc();
- get_device_once(master, slave, 1);
+ get_device_once(master, slave, SlaveName, 1);
}
}
@@ -418,9 +420,10 @@ pty_getpty(argc, argv, self)
VALUE rport = rb_obj_alloc(rb_cFile);
VALUE wport = rb_obj_alloc(rb_cFile);
+ char SlaveName[DEVICELEN];
MakeOpenFile(rport, rfptr);
MakeOpenFile(wport, wfptr);
- establishShell(argc, argv, &info);
+ establishShell(argc, argv, &info, SlaveName);
rfptr->mode = rb_io_mode_flags("r");