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");
-- Nobu Nakada