public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
From: Patrick Doyle <wpd@delcomsys.com>
To: cygwin <cygwin@sources.redhat.com>
Subject: Re: Why does scp leave ssh running? -- select() never returns
Date: Wed, 29 Nov 2000 19:21:00 -0000	[thread overview]
Message-ID: <3A25C7DA.6F76C8DA@delcomsys.com> (raw)
In-Reply-To: <3A22C383.5C16BBC8@delcomsys.com>

Patrick Doyle wrote:
> 
> When I run
> 
> scp somefile host:.
> 
> I am left with a copy of SSH running.  ...

I believe that have traced this problem down to the call to select() in
ssh.  Basically, it appears that ssh calls select() on a pipe.  If the
writer of that pipe closes it, select() never returns.  I have attached
code to the end of this email demonstrating this phenomenon.

I believe that I have traced this down to the call to PeekNamedPipe() in
"select.cc".  For some reason, on my W98 box, PeekNamedPipe() does not
return an error when the other end of the pipe is closed.

So, a few questions...
1) Is this behavior (of PeekNamedPipe()) a W9x bug?  (That is, does it
work correctly on NT/2K?)

2) What is the expected behavior of select() on a pipe when the writer
closes the pipe?  The code in ssh seems to imply that it should return,
probably with the "read" bit set for the closed pipe.

3) Does anybody have any ideas of how I might work around this problem,
preferably in cygwin?  (Otherwise, I could change the call to select()
"clientloop.c" to include a timeout).

4) Would folks mind trying this code and confirming if I am on the right
track or not?

Thanks for any help and/or advice...

--wpd

code follows... sorry about the leftover #ifdef debug stuff.

/************************************************************************
 * Simple program that demonstrates the "problem" with select(). 
Basically,
 * when a process is blocked on a select() call to read from a pipe, and
the
 * writer for the pipe closes it, the select call never returns (unless,
 * presumably, the timeout is set.
 *
 * This code demonstrats this phenomenon by creating a pipe, forking
 * a subprocess, closing the write side of the pipe (in the parent
process)
 * and performing a select() on the read side of the pipe.  Meanwhile,
the
 * child process closes the pipe, either after a timeout, or upon
receipt
 * if a SIGHUP.

************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/select.h>
#include <signal.h>

void
sighup(int x)
{
  /* do nothing */
}

int
main(int argc, char *argv[])
{
  int pid;
  int timeout;
  int pipe_fd[2];
  char buf[256];
  int bytes_read;
  int input_fd;
  fd_set readset;

  if (argc < 2) {
    timeout = 5;
  } else {
    if (sscanf(argv[1], "%d", &timeout) != 1 || timeout < 0) {
      fprintf(stderr, "usage: test1 [timeout]\n");
      exit(1);
    }
  }

  if (pipe(pipe_fd) < 0) {
    perror("pipe");
    exit(1);
  }
  if ((pid = fork()) == 0) {
    /* We are the child -- wait the specified timeout, write something
     * to the pipe, wait again, then close the pipe.
     */
    if (timeout == 0) {
      signal(SIGHUP, sighup);
      printf("Waiting for signal\n");
      sigpause(0);
    } else {
      sleep(timeout);
    }
#if 0
    printf("child: about to write to pipe\n");
    if (write(pipe_fd[1], "hello", sizeof("hello")) != sizeof("hello"))
{
      perror("child: write");
      exit(1);
    }
    if (timeout == 0) {
      signal(SIGHUP, sighup);
      printf("Waiting for signal\n");
      sigpause(0);
    } else {
      sleep(timeout);
    }
#endif
    if (close(pipe_fd[1]) < 0) {
      perror("child: close: pipe");
      exit(1);
    }
    printf("child: pipe closed, exiting\n");
    /* Exit successfully */
    exit(0);
  } else if (pid < 0) {
    /* The fork failed for some reason */
    perror("fork");
    exit(1);
  }
  /* We are the parent */
  close(pipe_fd[1]);
#if 1
  input_fd = pipe_fd[0];
#else
  input_fd = 0; /* Read from stdin */
#endif

  printf("parent: about to select on fd %d for reading\n", input_fd);
  FD_ZERO(&readset);
  FD_SET(input_fd, &readset);
  if (select(pipe_fd[0] + 1, &readset, 0, 0, 0) < 0) {
    perror("select");
    exit(1);
  }

  printf("parent: About to read from fd %d\n", input_fd);
  if ((bytes_read = read(input_fd, buf, sizeof(buf))) < 0) {
    perror("parent: read");
    exit(1);
  }
  buf[bytes_read] = 0;

  printf("read buffer of length %d: %s\n", bytes_read, buf);
  close(pipe_fd[0]);
  exit(0);
}

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

  parent reply	other threads:[~2000-11-29 19:21 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2000-11-27 12:26 Why does scp leave ssh running? Patrick Doyle
2000-11-28  2:12 ` Graham Bloice
2000-11-29 19:21 ` Patrick Doyle [this message]
2000-11-29 19:41   ` Why does scp leave ssh running? -- select() never returns Christopher Faylor
2000-11-30  6:15     ` Patrick Doyle
2000-11-30  6:35       ` Corinna Vinschen
2000-11-30  7:05         ` Patrick Doyle
2000-11-30 19:40       ` Patrick Doyle
2000-12-02 17:08         ` Christopher Faylor
2000-12-02 19:47           ` Patrick Doyle
2000-12-02 20:39             ` Christopher Faylor
2000-12-03  1:47               ` Corinna Vinschen
2000-12-11 10:19                 ` Patrick Doyle
2000-12-11 10:36                   ` Christopher Faylor
2000-12-11 10:56                     ` Patrick Doyle
2000-12-11 11:08                       ` Christopher Faylor
2001-01-06 19:21                       ` Patrick Doyle
2001-01-08  3:21                         ` Ehud Karni
2001-01-08  6:24                           ` Patrick Doyle
2000-12-12  5:46                   ` David Starks-Browning

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3A25C7DA.6F76C8DA@delcomsys.com \
    --to=wpd@delcomsys.com \
    --cc=cygwin@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).