Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perl 5.005_03 core dumps -- singal interrupt related #1005

Closed
p5pRT opened this issue Dec 29, 1999 · 76 comments
Closed

perl 5.005_03 core dumps -- singal interrupt related #1005

p5pRT opened this issue Dec 29, 1999 · 76 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 29, 1999

Migrated from rt.perl.org#1955 (status was 'resolved')

Searchable as RT1955$

@p5pRT
Copy link
Author

p5pRT commented Dec 29, 1999

From [email protected]

Perl core dumps shortly after I send an interrupt signal to my program.

Output from gdb​:

[bleh@​nut src]$ gdb perl core
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux"...
(no debugging symbols found)...

warning​: core file may not match specified executable file.
Core was generated by `perl ./psftp-core ssh​://bleh@​localhost/'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /lib/libnsl.so.1...done.
Reading symbols from /lib/libdl.so.2...done.
Reading symbols from /lib/libm.so.6...done.
Reading symbols from /lib/libc.so.6...done.
Reading symbols from /lib/libcrypt.so.1...done.
Reading symbols from /lib/ld-linux.so.2...done.
#0 chunk_alloc (ar_ptr=0x4013d040, nb=16) at malloc.c​:2804
2804 malloc.c​: No such file or directory.
(gdb) bt
#0 chunk_alloc (ar_ptr=0x4013d040, nb=16) at malloc.c​:2804
#1 0x400a840a in __libc_malloc (bytes=4) at malloc.c​:2643
#2 0x807a465 in Perl_safemalloc ()
#3 0x8088aea in Perl_sv_grow ()
#4 0x808b271 in Perl_newSV ()
#5 0x8098e8e in Perl_pp_split ()
#6 0x80b155d in Perl_runops_standard ()
#7 0x8059308 in perl_run ()
#8 0x805787f in main ()
#9 0x400681eb in __libc_start_main (main=0x8057810 <main>, argc=3,
  argv=0xbffffc34, init=0x8056b2c <_init>, fini=0x80b15cc <_fini>,
  rtld_fini=0x4000a610 <_dl_fini>, stack_end=0xbffffc2c)
  at ../sysdeps/generic/libc-start.c​:90
(gdb)

The core occurs when I send an interrupt while the program (attached
below) is in ssh_interface. It doesn't occur immeadietly, but shortly
therafter.

psftp.pl

#!/usr/bin/perl

#use Term​::ReadLine;
#use Term​::ReadKey;
#use IPC​::Open2;
use Getopt​::Std;
use URI​::URL;
#use strict;

# Configuration

# Location of helper programs (we assume its in path at the moment)
my $ssh = "psftp-ssh";
my $scp = "psftp-scp";
my $iprompt = "psftp​:";
my $pager = "less";
my $hdir = undef;
my $DEBUG = 1;
# End configuration

my $version = "0.05";
#my $term = new Term​::ReadLine;
my $state = 0;
my $user = undef;
my $pass = undef;
my $host = undef;
my $port = undef;
my $connected = 0;
my $pwd = undef;
my $prompt = "";
my $auth_mode = undef;
local *RFP;

# help related stuff
my @​commands = ();
my %help_hash = ();

my %optctl = ();
getopts('hu​:c​:',\%optctl);
if ( $optctl{"h"} ) {
  print "$0 $version\n";
  print "by Nadeem Riaz (nads\@​bleh.org)\n";
  print "Usage $0 [-u user] [-c conf_dir] [host|url]\n";
  exit;
}
$user = $optctl{"u"};
if ( defined($optctl{"c"}) && -d $optctl{"c"} ) {
  $hdir = $optctl{"c"};
} else {
  $hdir = "$ENV{HOME}/.psftp";
}
if ( ! -d $hdir ) {
  mkdir($hdir,0700);
}
unlink("$hdir/pass");
$SIG{"INT"} = \&do_exit;
load_help();

#print "Term Type​: " . $term->ReadLine() . "\n" if ( $DEBUG );
#sub test_func { open(FP,">log.1"); print FP "I was here\n"; close(FP) };
my ($key,$val);
#$my $attrib = $term->Attribs();
# $attrib->{"filename_quote_characters"} = "\\";
# $attrib->{"filename_quoting_function"} = \&test_func;
# $attrib->{"pre_input_hook"} = \&test_func;
# $attrib->{"display_match_list"} = \&test_func;
# $attrib->{"filename_completion_function"} = \&test_func;
# $attrib->{"char_is_quoted_p"} = "\\";

#$attrib->{"completion_word"} = [ sort(@​commands) ];
#$attrib->{"completion_append_character"} = "\"";
#$attrib->{"attempted_completion_function"} = \&do_pick_completion;
#$attrib->{"filename_quoting_function"} = sub { print "HEY\n" };
#$attrib->{"filename_dequoting_function"} = sub { print "HEY\n" };
#$attrib->{"filename_quote_characters"} = "b";
#$attrib->{"completer_word_break_characters"} = "\'`\@​\$><=;|&{( ";
#$attrib->{"completion_entry_function"} = undef;

# my $features = $term->Features();
#while ( ($key,$val) = each ( %{$attrib}) ) {
# print "$key = $val\n";
#}
#print $term->list_completion_function() . "\n";
if ( @​ARGV > 0 ) {
  open_host($ARGV[0]);
}

my $INT;
main_loop();

sub main_loop {
  while ( 1 ) {
  $prompt = "$iprompt $pwd> ";
  my ($line,$cmd);
  print "RIGHT BEFORE NEW TERM!\n";
  print "prompt> ";
  $line = <STDIN>;
# $line = $term->readline($prompt);
  print "RIGHT AFTER NEW TERM!\n";
  my ($cmd,$line) = split(/\s+/,$line,2);
  $cmd = lc($cmd);
  if ( $cmd eq "lpwd" ) {
  system("pwd");
  } elsif ($cmd eq "lcd" ) {
  do_local_cd($line);
  } elsif ($cmd eq "lls" || $cmd eq "ldir" ) {
  do_local_ls($line);
  } elsif ( $cmd eq "plls" || $cmd eq "pldir" ) {
  do_local_paged_ls($line);
  } elsif ( $cmd eq "lmkdir" ) {
  do_local_mkdir($line);
  } elsif ( $cmd eq "lrmdir" || $cmd eq "lrm" || $cmd eq
"ldel" ) {
  do_local_rm($line);
  } elsif ( $cmd eq "lchown" ) {
  do_local_chown($line);
  } elsif ( $cmd eq "lchmod" ) {
  do_local_chmod($line);
  } elsif ( $cmd eq "put" ) {
  do_put($line);
  } elsif ( $cmd eq "mput" ) {
  do_mput($line)
  } elsif ( $cmd eq "get" ) {
  do_get($line);
  } elsif ( $cmd eq "mget" ) {
  do_mget($line);
  } elsif ($cmd eq "cd" ) {
  do_remote_cd($line);
  } elsif ( $cmd eq "pwd" ) {
  do_remote_pwd();
  } elsif ( $cmd eq "ls" || $cmd eq "dir" ) {
  do_remote_ls($line);
  } elsif ( $cmd eq "ls" || $cmd eq "dir" ) {
  do_remote_paged_ls($line);
  } elsif ( $cmd eq "mkdir" ) {
  do_remote_mkdir($line);
  } elsif ( $cmd eq "rmdir" || $cmd eq "rm" || $cmd eq "del"
) {
  do_remote_rm($line);
  } elsif ( $cmd eq "chown" ) {
  do_remote_chown($line);
  } elsif ( $cmd eq "chmod" ) {
  do_remote_chmod($line);
  } elsif( $cmd eq "open" ) {
  open_host($line);
  } elsif ( $cmd eq "close" ) {
  close_host();
  } elsif ( $cmd eq "clear" ) {
  system("clear"); # have to replace this later
  } elsif ( $cmd eq "help" ) {
  do_help($line);
  } elsif ( $cmd eq "set" ) {
  do_set();
  } elsif ($cmd eq "save" ) {
  do_save();
  } elsif ( $cmd eq "exit" || $cmd eq "quit" ) {
  do_exit();
  } elsif ( $cmd eq "") {
  next;
  } else {
  print "Bad command​: $cmd\n";
  }
  print "END PF LONG AS ELS/IF\n";
  }
  exit;
}

sub open_host {
  my $line = shift @​_;
  $host = undef;
  $user = undef;
  $pass = undef;
  $port = undef;
  $auth_mode = undef;
  $pwd = "";
  if ( defined($line) ) {
  if ( $line =~ /^ssh\​:\/\//i ) {
  my $url = new URI​::URL $line;
  $host = $url->host;
  $port = $url->port;
  $user = $url->user;
  $pass = $url->password;
  } else {
  $host = $line;
  }
  }
  if ( ! defined($host) || $host eq "" ) {
  print "Enter host name​: ";
  chomp($host = <STDIN>);
  }
  if ( ! defined($user) || $user eq "" ) {
  print "Enter user name​: ";
  chomp($user = <STDIN>);
  }
  print "Connecting to $host....\n";
  ($auth_mode,$pwd) = get_auth_mode() if ( ! defined($auth_mode) ||
$auth_mode eq "" );
  if ( ! defined($auth_mode) ) {
  print "Couldn't connect to $host\n";
  unlink("$hdir/pass");
  return 0;
  }
  print "connected!\n";
  $connected = 1;
  print "Connection successful to $host, auth_mode = $auth_mode\n"
if ( $DEBUG );
  $pwd = remote_cd("") if ( ! defined($pwd) || $pwd eq "" );
}

sub close_host {
  if ( ! $connected ) {
  print "Not connected\n";
  return;
  }
  $connected =0;
  $host = undef;
  $user = undef;
  $pass = undef;
  $port = undef;
  $auth_mode = undef;
  $pwd = "";
  unlink("$hdir/pass");
}

sub get_auth_mode {
  my $c = "$ssh $host \"echo no pass ; pwd\" 2>&1";
  my $oldint = $SIG{'INT'};
  $SIG{'INT'} = \&ssh_interrupt;
  open(RFP,"$c |") || die "Couldn't create pipe​: $!";
  sleep(1);
 
  my (@​lo,$line);
  eval {
  $SIG{"ALRM"} = sub {
  print "Timeout on auth mode!\n";
  if ( ! defined($pass) || $pass eq "") {
  print "Enter password​: ";
  $pass = <STDIN>;
  chomp($pass);
  # ReadMode 4;
  # my $key = "";
  #while ($key ne "\n" ) {
  # $key = ReadKey(1);
  # $pass .= $key;
  #}
  #chomp($pass);
  #ReadMode 0;
  #print "\n";
  }
  write_pass($pass);
  $SIG{"ALRM"} = sub { print "Connection to
$host timed out\n"; die "Couldn't connect to $host" };
  alarm 30;
  };
  alarm(5);
  $line = <RFP>;
  alarm 0;
  sleep(1);
  @​lo = <RFP>;
  };
  if ( $@​ ) {
  return undef;
  }
 
  alarm 0;
  close(RFP) if ( *RFP );
  $SIG{"INT"} = $oldint;
  my ($gpwd,$auth);
  if ( $line =~ /Bad host name/i ) {
  print "Bad host name\n";
  return (undef,undef);
  } elsif ($line =~ /password/i ) {
  my $o = shift @​lo;
  if ( $o =~ /Permission denied/ ) {
  print "Permission denied\n";
  return (undef,undef);
  } elsif ( $o !~ /no pass/ ) {
  print "INTERNAL ERROR!​: $o \n";
  return (undef,undef);
  }
  $auth = "password";
  } elsif ( $line =~ /no pass/i ) {
  $auth = "RSARhost";
  } else {
  print "ERROR Couldn't determine authentication mode\n";
  return (undef,undef);;
  }
  $gpwd = shift(@​lo);
  chomp($gpwd);
  return ($auth,$gpwd);
}

sub write_pass {
  my $pass = shift @​_;
  local *pFP;
  open(pFP,">$hdir/pass") || die "Couldn't open pass file!\n$!\n";
  print pFP "$pass\n";
  close(pFP);
}

sub remote_cd {
  my $dir = shift @​_;
  my $c = "cd $dir 2>&1; pwd";
  my @​cd_output = execute_remote_cmd($c);
  my $cdo = $cd_output[0];
  chomp($cdo);
  if ( $cdo =~ /No such file or directory/ ) {
  return (undef,"No such file or directory");
  } elsif ($cdo =~ /Not a directory/ ) {
  return (undef,"Not a directory");
  } elsif ( $cdo =~ /Permission denied/ ) {
  return(undef,"Permission deinied");
  } elsif ( ! defined($cdo) ) {
  return (undef,"Internal Error");
  }
  return $cdo;
}

sub execute_remote_cmd {
  my ($cmd,$print) = (@​_);
  my $c = "$ssh $host \"cd $pwd ; $cmd\" 2>&1";
  return ssh_interface($c,$print);
}

sub ssh_interface {
  my ($c,$print) = (@​_);
  print "-- begin ssh interface --\n" if ( $DEBUG );
# open2(\*RFP,\*WFP,$c) || die "Couldn't create pipe​: $!";
  print "current int = $SIG{'INT'}\n";
  my $oldint = $SIG{'INT'};
  print "old int = $oldint\n";
  $SIG{'INT'} = \&ssh_interrupt;
  print "new int = $SIG{'INT'}\n";
  open(RFP,"$c |");
  sleep(1);
  if ( $auth_mode eq "password" ) {
# write_pass($pass);
# print WFP "$pass\n";
  <RFP>;
  }
  sleep(1);
  my @​output;
  if ( $print ) {
  my $c;
  $| =1; # Flush after every print
  while ( read(RFP,$c,1) ) {
  print $c;
  }
  $| = 0;
  } else {
  @​output = <RFP>;
  }
  print("-- end ssh interface --\n") if ( $DEBUG );
  if ( $INT ) {
  $INT = 0;
  return 0;
  }
  close(RFP);
  print "CLOSE SUCCESFUL\n";
  $SIG{'INT'} = $oldint;
  if ( $print ) {
  return 1;
  } else {
  return @​output;
  }
}

sub do_remote_cd {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $dir = shift @​_;
  my @​cd_output = remote_cd($dir);
  if ( defined($cd_output[0]) ) {
  $pwd = $cd_output[0];
  } else {
  print "$cd_output[1]\n";
  }
}

sub do_remote_mkdir {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $dir = shift @​_;
  execute_remote_cmd("mkdir $dir",1);
}

sub do_remote_rm {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $files = shift @​_;
  execute_remote_cmd("rm -rf $files",1);
}

sub do_remote_chown {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $files = shift @​_;
  execute_remote_cmd("chown $files",1);
}

sub do_remote_chmod {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $files = shift @​_;
  execute_remote_cmd("chmod $files",1);
}

sub do_remote_pwd {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  print "$pwd\n";
}

sub do_remote_ls {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $args = shift @​_;
  execute_remote_cmd("ls $args",1);
  print "REMOTE LS RETURN SUCCESSFUL\n";
}

sub do_remote_paged_ls {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  local *lFP;
  my $args = shift @​_;
  my @​lines = execute_remote_cmd("ls $args");
  if ( ! open(lFP,"| $pager") ) {
  print "Couldnt pipe to pager!\n";
  return;
  }
  my $line;
  foreach $line (@​lines) {
  print lFP $line;
  }
}

sub do_local_cd {
  my $dir = shift @​_;
  if ( ! chdir("$dir") ) {
  print "Couldn't change to dir $dir​: $!\n";
  return undef;
  }
  return 1;
}

sub do_local_ls {
  my $line = shift @​_;
  system("ls $line");
}

sub do_local_paged_ls {
  my $line = shift @​_;
  system("ls $line | $pager");
}

sub do_local_mkdir {
  my $dir = shift @​_;
  if ( ! mkdir("$dir",0700) ) {
  print "Couldn't make local dir $dir​: $!\n";
  return undef;
  }
  return 1;
}

sub do_local_rm {
  my $files = shift @​_;
  system("rm -rf $files");
}

sub do_local_chown {
  my $files = shift @​_;
  system("chown $files");
}

sub do_local_chmod {
  my $files = shift @​_;
  system("chmod $files");
}

sub do_put {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $line = shift @​_;
  if ( ! defined($line) || $line eq "" ) {
  print "No file given!\n";
  return 0;
  }
 
  # Break up args, and assign them to appropriate var
  my ($arg,$file,$remote,@​jun) = split_args($line);
  my $options = "";
  if ( $arg eq "-r" || $arg eq "-R" ) {
  $options = "-r";
  } else {
  $remote = $file;
  $file = $arg;
  }
 
  # Check file|dir exist
  if ( $options ) {
  if ( ! -d $file && ! -f $file ) {
  print "'$file' is not a file or directory (does it
exist?)\n";
  return 0;
  }
  } else {
  if ( ! -f $file ) {
  print "'$file' is not a normal file\n";
  return 0;
  }
  }

  put_files([ $file ],$remote,$options);
  return;
}

sub do_mput {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $line = shift @​_;
  if ( ! defined($line) || $line eq "" ) {
  print "No file given!\n";
  return 0;
  }
 
  # Break up args, and assign them to appropriate var
  my (@​files) = split_args($line);
  my $options = "";
  my $arg = shift(@​files);
  if ( $arg eq "-r" || $arg eq "-R" ) {
  $options = "-r";
  } else {
  unshift(@​files,$arg);
  }
 
  if (@​files < 1 ) {
  print "No files given!\n";
  return 0;
  }
 
  my ($file,@​put_list);
  foreach $file (@​files) {
  next if ( $file eq "" );
  print "Trying $file\n" if ( $DEBUG );
  my $print_glob_errors = 1;
  if ( $options ) {
  if ( -d $file || -f $file ) {
  push(@​put_list,$file);
  $print_glob_errors = 0;
  }
  } else {
  if ( -f $file ) {
  push(@​put_list,$file);
  $print_glob_errors = 0;
  }
  }
  my ($glob,@​glob_list);
  @​glob_list = glob($file);
  glob_for​: foreach $glob (@​glob_list) {
  print "\tglob'd​: $glob\n" if ( $DEBUG );
  my $p;
  foreach $p (@​put_list) {
  next glob_for if ( $p eq $glob );
  }
  # Check file|dir exist
  if ( $options ) {
  if ( ! -d $glob && ! -f $glob ) {
  print "'$glob' is not a file or
directory (does it exist?)\n" if ( $print_glob_errors );
  next;
  }
  } else {
  if ( ! -f $glob ) {
  print "'$glob' is not a normal
file\n" if ( $print_glob_errors );
  next;
  }
  }
  push(@​put_list,$glob)
  }
  }
  put_files(\@​put_list,undef,$options);
  return 1;
}

sub put_files {
  my ($local,$remote,$options) = (@​_);
  print "put_file​: options = $options Trying to put @​{$local} as
$remote\n" if ( $DEBUG );
  my $c = "$scp -a -Q ";
  if ( defined($options) && $options ne "") {
  $c .= " $options ";
  }
 
  my @​local = @​{$local};
  my $x;
  for ($x=0;$x<@​local;$x++) {
  $local[$x] = shell_escape($local[$x]);
  }
 
  $remote = shell_escape($remote);
  my $f = "$pwd/$remote";
  if ( $remote =~ /^\// ) {
  $f = $remote;
  }
  ssh_interface("$c @​local $user\@​$host​:$f 2>&1",1);
}

sub do_get {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  my $file = shift @​_;
  if ( ! defined($file) || $file eq "" ) {
  print "No file given!\n";
  return 0;
  }
  my ($args,$nf) = split(/\s+/,$file,2);
  my $options = "";
  if ( defined($nf) && $nf ne "" && ($args eq "-r" || $args eq "-R")
){
  $options = "-r";
  $file = $nf;
  }
  get_file($file,undef,$options);
  return;
}

sub do_mget {
  if ( ! $connected ) {
  print "Not connected to host!\n";
  return;
  }
  print "Feature not done yet\n";
  return;
}

sub get_file {
  my ($remote,$local,$options) = (@​_);
  print "get_file​: options = $options Trying to get $remote as
$local\n" if ( $DEBUG );
  my $c = "$scp -a -Q ";
  if ( defined($options) && $options ne "") {
  $c .= " $options ";
  }
  $local = shell_escape($local);
  $remote = shell_escape($remote);
  if ( $local eq "" ) { $local = "./"; }
  my $f = "$pwd/$remote";
  if ( $remote =~ /^\// ) {
  $f = $remote;
  }
  ssh_interface("$c $user\@​$host​:$f $local 2>&1",1);
}

sub do_help {
  if ( @​commands < 1 ) {
  load_help();
  }
  my $cmd = shift @​_;
  if ( defined($cmd) && $cmd ne "" ) {
  if ( exists $help_hash{$cmd} ) {
  print "$cmd​: $help_hash{$cmd}";
  } else {
  print "There is no help avaible for $cmd\n";
  }
  } else {
  my @​sc = sort(@​commands);
  my ($x,$y,$sc);
  for ($x=0;$x<5;$x++) {
  for ($y=0;$y<6;$y++) {
  $sc->[$x]->[$y] = $sc[($x*6)+$y];
  }
  }
  print "Commands available​:\n";
# print "commands​: @​sc\n" if ( $DEBUG );
  for ($x=0;$x<6;$x++) {
  print
"$sc->[0]->[$x]\t\t$sc->[1]->[$x]\t\t$sc->[2]->[$x]\t\t$sc->[3]->[$x]\t\t$sc->[4]->[$x]\n";
  }
  }
}

sub load_help {
  @​commands = qw(lpwd lcd lls plls lmkdir lrm lchown lchmod put
mput get mget cd pwd ls pls mkdir rm rmdir chown chmod open close clear
exit help set save);
  $help_hash{"lpwd"} = "display local parent directory\nUsage​:
lpwd\n";
  $help_hash{"lcd"} = "change local directory\nUsage​: lcd <dir>\n";
  $help_hash{"lls"} = "display list of file on local machine\nUsage​:
lls [dir]\n";
  $help_hash{"plls"} = "displays list of files on local machine,
paged with program given by pager variable\nUsage​: plls [dir]\n";
  $help_hash{"lmkdir"} = "create a directory on local
machine\nUsage​: lmkdir <dir>\n";
  $help_hash{"lrm"} = "delete files or directories on local
machine\nUsage​: lrm <file|dir>\n";
  $help_hash{"lchown"} = "change ownership of file on local
machine\nUsage​: lchown <dir>\n";
  $help_hash{"lchmod"} = "change mode of file on local
machine\nUsage​: lchmod <file>\n";
  $help_hash{"put"} = "uploads a file or dir to the remote
machine\nUsage​: put [-r] <file|dir> <name of file|dir on remote
machine>\n";
  $help_hash{"mput"} = "uploads files and/or dirs to the remote
machine\nUsage​: mput [-r] <file list|dir list|globs|any mix thereof>\n";
  $help_hash{"get"} = "No help avaible on this yet\n";
  $help_hash{"mget"} = "No help avaible on this yet\n";
  $help_hash{"pwd"} = "display local parent directory\nUsage​:
pwd\n";
  $help_hash{"cd"} = "change local directory\nUsage​: cd <dir>\n";
  $help_hash{"ls"} = "display list of file on remote machine\nUsage​:
ls [dir]\n";
  $help_hash{"pls"} = "displays list of files on remote machine,
paged with program given by pager variable\nUsage​: pls [dir]\n";
  $help_hash{"mkdir"} = "create a directory on remote
machine\nUsage​: mkdir <dir>\n";
  $help_hash{"rm"} = "delete files or directories on remote
machine\nUsage​: rm <file|dir>\n";
  $help_hash{"rmdir"} = $help_hash{"rm"};
  $help_hash{"chown"} = "change ownership of file on remote
machine\nUsage​: chown <dir>\n";
  $help_hash{"chmod"} = "change mode of file on remote
machine\nUsage​: chmod <file>\n";
  $help_hash{"open"} = "opens a connection to a host\nUsage​: open
[host|url]\n";
  $help_hash{"close"} = "close current connection\nUsage​: close\n";
  $help_hash{"help"} = "displays commands avaible or help on a
command\nUsage​: help [command]";
  $help_hash{"exit"} = "exits program\nUsage​: exit\n";
  $help_hash{"set"} = "displays all variables, request var, or sets
vars depending on arguments\nUsage​: set [var] [new value]\n";
  $help_hash{"save"} = "saves current variable values to local
config file\nUsage​: save\n";
}

sub do_exit {
  if ( $connected ) {
  close_host();
  }
  #ReadMode 0;
  unlink("$hdir/pass");
  # On interrupts ReadLine might mangle the term, thus we
  # call reset to fix us up
  system("reset -Q");
  exit;
}

sub ssh_interrupt {
  $INT = 1;
  $SIG{"INT"} = \&do_exit;
  print "SSH INTERRUPT\n" if ( $DEBUG );
  close(RFP);
  return 1;
}

sub do_set {
  print "Feature not done yet\n";
  return 0;
}

sub do_save {
  print "Feature not done yet\n";
  return 0;
}

sub shell_escape {
  my $line = shift @​_;
  $line =~ s/\"/\\"/g;
  $line =~ s/\'/\\'/g;
  $line =~ s/\s/\\ /g;
  $line =~ s/\!/\\!/g;
  $line =~ s/\[/\\[/g;
  $line =~ s/\]/\\]/g;
  $line =~ s/\(/\\(/g;
  $line =~ s/\)/\\)/g;
  return $line
}

#sub do_pick_completion {
# my ($text, $line, $start, $end) = @​_;
# if (substr($line, 0, $start) =~ /^\s*$/) {
# return
$term->completion_matches($text,$attrib->{list_completion_function});
# } else {
# my ($cmd,$rline) = split(/\s+/,$line);
# $cmd = lc($cmd);
# if ( ($cmd =~ /^l/ && $cmd ne "ls") || $cmd eq "plls" ||
$cmd eq "put" || $cmd eq "mput") {
# # Local file completion
# my @​list =
$term->completion_matches($text,$attrib->{filename_completion_function});
# $state++;
# my $x;
# for ($x=0;$x<@​list;$x++) {
# $list[$x] = shell_escape($list[$x]);
# }
# open(FP,">log.1");
# print FP "urmfg​: $state​: @​list\n";
# close(FP);
# return (@​list);
# } else {
# $attrib->{"inhibit_completion"} = 1;
# return ();
# }
#
# }
#}

sub split_args {
  my $text = shift @​_;
  my ($space,$escape,$open_quote);
  my ($warg,@​args);
  my ($x);
 
  # Split line into args
  for($x=0;$x<length($text);$x++) {
  if ( substr($text,$x,1) eq "\\" ) {
  if ( $escape ) {
  $warg .= "\\";
  } else {
  $escape = 1;
  next;
  }
  } elsif ( !$escape && substr($text,$x,1) eq "\"" ) {
  if ( $open_quote ) {
  # New Arg
  push(@​args,$warg);
  $warg ="";
  $open_quote = 0;
  } else {
  $open_quote = 1;
  }
  next;
  } elsif ( ! $escape && ! $open_quote && substr($text,$x,1)
eq " " ) {
  if ( ! $space ) {
  # New Arg
  push(@​args,$warg);
  $warg ="";
  $space = 1;
  }
  next;
  }
  if ( $space ) {
  $space = 0;
  } elsif ( $escape ) {
  $escape = 0;
  }
  $warg .= substr($text,$x,1);
  }
  push(@​args,$warg);
  my $y;
  for ($y=0;$y<@​args;$y++) {
  print "$y. '$args[$y]'\n" if ( $DEBUG );
  }
  return (@​args);
}

# END PSFTP.pl

Perl Info


Site configuration information for perl 5.00503:

Configured by root at Mon Aug 30 23:08:56 EDT 1999.

Summary of my perl5 (5.0 patchlevel 5 subversion 3) configuration:
  Platform:
    osname=linux, osvers=2.2.5-22smp, archname=i386-linux
    uname='linux porky.devel.redhat.com 2.2.5-22smp #1 smp wed jun 2 09:11:51 edt 1999 i686 unknown '
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=undef useperlio=undef d_sfio=undef
  Compiler:
    cc='cc', optimize='-O2', gccversion=egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
    cppflags='-Dbool=char -DHAS_BOOL -I/usr/local/include'
    ccflags ='-Dbool=char -DHAS_BOOL -I/usr/local/include'
    stdchar='char', d_stdstdio=undef, usevfork=false
    intsize=4, longsize=4, ptrsize=4, doublesize=8
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    alignbytes=4, usemymalloc=n, prototype=define
  Linker and Libraries:
    ld='cc', ldflags =' -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -ldl -lm -lc -lposix -lcrypt
    libc=, so=so, useshrplib=false, libperl=libperl.a
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'

Locally applied patches:
    


@INC for perl 5.00503:
    /usr/lib/perl5/5.00503/i386-linux
    /usr/lib/perl5/5.00503
    /usr/lib/perl5/site_perl/5.005/i386-linux
    /usr/lib/perl5/site_perl/5.005
    .


Environment for perl 5.00503:
    HOME=/home/bleh
    LANG (unset)
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/bin:/usr/bin::/usr/X11R6/bin:/sbin:/usr/sbin:/usr/local/java/jdk/bin:/home/bleh/usr/bin:/home/bleh/work/code/cli
    PERL_BADLANG (unset)
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Dec 30, 1999

From [Unknown Contact. See original ticket]

<nads@​bleh.org> writes​:

This is a bug report for perl from nads@​bleh.org,
generated with the help of perlbug 1.26 running under perl 5.00503.

-----------------------------------------------------------------
[Please enter your report here]

Perl core dumps shortly after I send an interrupt signal to my program.

Signals can do that to any perl. Only the most trivial of signal handlers
are safe. They must not allocate any memory at all (very hard to be sure
of in perl code) as the signal may have occured in the memory allocator
and that is probably not re-entrant.

There are various approaches to making signals usable which
may be in the development track.

Both Tk and the Event modules have 'synchronous' signals implemented
at the C level, but delayed until the next "event despatch" occurs.

#0 chunk_alloc (ar_ptr=0x4013d040, nb=16) at malloc.c​:2804
2804 malloc.c​: No such file or directory.
(gdb) bt
#0 chunk_alloc (ar_ptr=0x4013d040, nb=16) at malloc.c​:2804
#1 0x400a840a in __libc_malloc (bytes=4) at malloc.c​:2643

Pretty typical ...

$SIG{"INT"} = \&do_exit;
sub do_exit {
if ( $connected ) {
close_host();
}
#ReadMode 0;
unlink("$hdir/pass");
# On interrupts ReadLine might mangle the term, thus we
# call reset to fix us up
system("reset -Q");
exit;
}

Far, far too complex.

--
Nick Ing-Simmons

@p5pRT
Copy link
Author

p5pRT commented Jan 4, 2000

From [Unknown Contact. See original ticket]

Nick Ing-Simmons writes​:

Perl core dumps shortly after I send an interrupt signal to my program.

Signals can do that to any perl. Only the most trivial of signal handlers
are safe.

This is wrong. No signal handlers are safe.

Hope this helps (why should I repeat it again and again?),
Ilya

P.S.

There are various approaches to making signals usable which
may be in the development track.

I wonder why not we add something like

  $SIG{CHLD} = [inc => \$counter, set => [\$foo, 13], pid => \$pid];

and avoid all the problems with a Perl function call altogether...

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From @TimToady

Ilya Zakharevich writes​:
: I wonder why not we add something like
:
: $SIG{CHLD} = [inc => \$counter, set => [\$foo, 13], pid => \$pid];
:
: and avoid all the problems with a Perl function call altogether...

Bletch, in a vague sort of way.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From [Unknown Contact. See original ticket]

Larry Wall writes​:

Ilya Zakharevich writes​:
: I wonder why not we add something like
:
: $SIG{CHLD} = [inc => \$counter, set => [\$foo, 13], pid => \$pid];
:
: and avoid all the problems with a Perl function call altogether...

Bletch, in a vague sort of way.

But comparing to what we have now it would be a paradise. ;-)

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From @TimToady

Ilya Zakharevich writes​:
: Larry Wall writes​:
: >
: > Ilya Zakharevich writes​:
: > : I wonder why not we add something like
: > :
: > : $SIG{CHLD} = [inc => \$counter, set => [\$foo, 13], pid => \$pid];
: > :
: > : and avoid all the problems with a Perl function call altogether...
: >
: > Bletch, in a vague sort of way.
:
: But comparing to what we have now it would be a paradise. ;-)

I was bletching the interface, not the implementation. I agree that
the implementation of the current interface could use improvement.
This has all been discussed before. We need to delay sub invocations
until we know we're in a safe state, such as the beginning of a
statement, or at the interator of any looping constructs, including
regular expressions. Of course, within regular expressions we'd have
to take extra care to be re-entrant, but the swash routines already do
that now--see Perl_save_re_context().

An interesting question is where to install the checks in the regular
expression engine such that we do not suffer significant overhead,
while at the same time guaranteeing that the evaluation will progress
to a check point in reasonable time, say, less than a second or so.
Possibly the right time to check is at the longest failure of a * or +,
just before we start backing off. Possibly we should just check on
every backoff, if accessing the global "signal_pending" variable is
cheap.

In this scheme, here's our C signal handler​:

  Signal_t
  Perl_sighandler(int sig)
  {
  PL_signal_count[sig]++;
  PL_signal_pending++;
  }

Seems pretty safe to me.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From [Unknown Contact. See original ticket]

On Mon, Jan 10, 2000 at 01​:28​:16PM -0800, Larry Wall wrote​:

Ilya Zakharevich writes​:
: Larry Wall writes​:
: >
: > Ilya Zakharevich writes​:
: > : I wonder why not we add something like
: > :
: > : $SIG{CHLD} = [inc => \$counter, set => [\$foo, 13], pid => \$pid];
: > :
: > : and avoid all the problems with a Perl function call altogether...
: >
: > Bletch, in a vague sort of way.
:
: But comparing to what we have now it would be a paradise. ;-)

I was bletching the interface, not the implementation. I agree that
the implementation of the current interface could use improvement.

And I was saying that a change of the interface can make the
improvements to become improvements, not changes with some positive
and some negative effects.

This has all been discussed before. We need to delay sub invocations
until we know we're in a safe state, such as the beginning of a
statement, or at the interator of any looping constructs, including
regular expressions.

No, we do not *need* to delay sub invocations. Delaying the
invocation is one of the possible workarounds to the current
disaster. It has many negative effects, like being a NOP in the case
of a long-running opcode.

And if you want the delayed semantic, you may do

$SIG{CHLD} = [delayed => sub {...} ];

And you can do

$SIG{CHLD} = [delayed => sub {...}, repeated => [2, sub {...}] ];

which might mean that if another signal appears when one is delayed
(meaning​: AHA, something dangerous happens​: signal was not served,
probably a long-running opcode, we need some recovery action), another
sub (or maybe another %SIG-compatible specification, as at the start)
should be run.

Of course, within regular expressions we'd have
to take extra care to be re-entrant, but the swash routines already do
that now--see Perl_save_re_context().

Which is an obvious bletch.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From @TimToady

Ilya Zakharevich writes​:
: > This has all been discussed before. We need to delay sub invocations
: > until we know we're in a safe state, such as the beginning of a
: > statement, or at the interator of any looping constructs, including
: > regular expressions.
:
: No, we do not *need* to delay sub invocations. Delaying the
: invocation is one of the possible workarounds to the current
: disaster. It has many negative effects, like being a NOP in the case
: of a long-running opcode.

And in what way does your proposal help this? What interrupts the
long running opcode in your version of reality? You modified some
existing variables, so what?

: And if you want the delayed semantic, you may do
:
: $SIG{CHLD} = [delayed => sub {...} ];
:
: And you can do
:
: $SIG{CHLD} = [delayed => sub {...}, repeated => [2, sub {...}] ];
:
: which might mean that if another signal appears when one is delayed
: (meaning​: AHA, something dangerous happens​: signal was not served,
: probably a long-running opcode, we need some recovery action), another
: sub (or maybe another %SIG-compatible specification, as at the start)
: should be run.

That's more needless complexity. This should be hidden from the user.
Immediate dispatch on duplicate signals could be done in the current
scheme as well without exposing it to the poor user. And that's only
necessary if we aren't smart enough to find all the proper check
points, which I think we are.

: > Of course, within regular expressions we'd have
: > to take extra care to be re-entrant, but the swash routines already do
: > that now--see Perl_save_re_context().
:
: Which is an obvious bletch.

But then you're talking implementation again. I'd rather see the
complexity in the implementation than in the interface. Perl was
intended to be easy to use, not necessarily easy to implement. Of
course, for a given interface, a simpler implementation is nice, but
that's not what we're optimizing for.

And the whole idea of signals is so busted anyway that I don't think a
complex interface is worth it. Save the TMTOWTDI for more important stuff.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From [Unknown Contact. See original ticket]

On Mon, Jan 10, 2000 at 03​:54​:56PM -0800, Larry Wall wrote​:

Ilya Zakharevich writes​:
: > This has all been discussed before. We need to delay sub invocations
: > until we know we're in a safe state, such as the beginning of a
: > statement, or at the interator of any looping constructs, including
: > regular expressions.
:
: No, we do not *need* to delay sub invocations. Delaying the
: invocation is one of the possible workarounds to the current
: disaster. It has many negative effects, like being a NOP in the case
: of a long-running opcode.

And in what way does your proposal help this? What interrupts the
long running opcode in your version of reality?

The kernel, of course.

You modified some existing variables, so what?

Modification of existing variables is the smallest problem of Perl
signal handlers. All the real damage is done during the subroutine
call frame. And using the proposed interface you do not need the
subroutine call. Moreover, you may insure that the changes you do
from the signal handler are atomic (say, by croaking if an atomic
change is not possible).

: And you can do
:
: $SIG{CHLD} = [delayed => sub {...}, repeated => [2, sub {...}] ];
:
: which might mean that if another signal appears when one is delayed
: (meaning​: AHA, something dangerous happens​: signal was not served,
: probably a long-running opcode, we need some recovery action), another
: sub (or maybe another %SIG-compatible specification, as at the start)
: should be run.

That's more needless complexity. This should be hidden from the user.
Immediate dispatch on duplicate signals could be done in the current
scheme as well without exposing it to the poor user.

Yes, it may be done. However, it is done *dangerously*, why in my
scheme it may be done safely.

And if you do not like the interface, write a module which
deparses

sub { ++$count; return }

to [ inc => \$count ]. Make assignment to $SIG autoload this module.
If deparse fails, enable the delayed samantic.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From [Unknown Contact. See original ticket]

Ilya Zakharevich (lists.p5p)​:

And if you do not like the interface, write a module which
deparses

sub { ++$count; return }

to [ inc => \$count ]. Make assignment to $SIG autoload this module.
If deparse fails, enable the delayed samantic.

I hate to suggest this, but wouldn't
  $SIG{FOO} = sub { ++$count; return }
be easier for all concerned?

The even-numbered elements to your anon array there (not even a hash.
furrfu.) appear to be forming a `sub-language' - inc, set, and so on.
This seems wasteful​:
  If you disallow running arbitary code, you're restricting people.
  If you allow, say, a `[code => sub { ... }]', everyone will use that
instead of the other `instructions', out of laziness.

Either way, you lose. Blech, in fact.

--
Generic Fortune.

@p5pRT
Copy link
Author

p5pRT commented Jan 10, 2000

From @samtregar

On 11 Jan 2000, Simon Cozens wrote​:

I hate to suggest this, but wouldn't
$SIG{FOO} = sub { ++$count; return }
be easier for all concerned?

The even-numbered elements to your anon array there (not even a hash.
furrfu.) appear to be forming a `sub-language' - inc, set, and so on.
This seems wasteful​:
If you disallow running arbitary code, you're restricting people.
If you allow, say, a `[code => sub { ... }]', everyone will use that
instead of the other `instructions', out of laziness.

True, but currently a sub {} cannot be executed by a signal handler in a
safe manner. If a signal arrives at a critical moment, such as inside
malloc or some other non-reentrent system call, then even calling a simple
sub {} is not garaunteed to be safe. Ilya's "sub-language" is one
proposal to solve this problem - presumably some XSUB would be cooked up
to parse the defined sublanguage and take action when recieving
signals.

-sam

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Mon, 10 Jan 2000 13​:28​:16 -0800 (PST)
  Larry Wall <larry@​wall.org> wrote
  in <200001102128.NAA15919@​kiev.wall.org>​:

:We need to delay sub invocations until we know we're in a safe state,
:such as the beginning of a statement, or at the interator of any looping
:constructs, including regular expressions.

What about slow-running ops? It seems like some of them require more
careful work than others. For example, sort() on a large data set can
take a swell spell, and readline() on a serial line or stream connection
can take virtually infinite time. In the latter case, I suppose we have
the EINTR and the SA_RESTART dodge. Here's my list of such operators​:

  sys related​: accept, close, connect, fcntl, flock, getc, ioctl,
  open, print, read, readline, recv, send, syscall,
  sysread, syswrite, wait, waitpid

Those aren't that bad. It's the others that seem more challenging.
For example​:

  indirect calls​: sort, map, grep

Where do those take the signal? What if it's a built-in sorting, such as
C<sort @​array>, or using the newly optimized built-ins (from perldelta​:
``Simple sort() using { $a <=> $b } and the like are optimized Many
common sort() operations using a simple inlined block are now optimized
for faster performance.'')?

What about system() and `backticks`? Are these part of the sys-related
case above? Is glob() an issue? It uses many readdir()s, unless it's not
built-in, in which case it will be using an external program. Does this
fall into the system() and `backtick` case?

Is sleep() a sys-related case?

What about list-context flipflops? "a" .. "zzzzz" takes a long time
(well, until you hit out of memory :-).

How about the dofile and require operators? Is it safe to permit
receipt of the signal once they've compiled and once they're executing
their newly compiled code? I assume that the import() component of
the use operator would be signallable during its execution.

Finally, let's have some fun ones. What about tie() and its related
intercepts? There's no reason to imagine that any of the TIE*() functions
shall complete in "reasonable" (non-arbitrary) time. At what granularity
should they be interruptible? Consider​:

  tie %mib, 'Tie​::SMTP', $remhost;
  $desc = $mib{ "system.sysDescr" };

The tie itself might take a long time because $remhost is unreachable.
If there's underlying Perl code that's stuck in one of the previously
mentioned cases (e.g. connect), perhaps this suffices. Same situation
with the tied()d call to FETCH() in the next line.

But what if it's in XS code? How will reliable signal delivery interact
with XS code?

--tom

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

Larry> That's more needless complexity.
Larry> This should be hidden from the user.

Ilya> And if you do not like the interface, write a module which
Ilya> deparses
Ilya> sub { ++$count; return }
Ilya> to [ inc => \$count ]. Make assignment to $SIG autoload this module.
Ilya> If deparse fails, enable the delayed semantic.

This still falls under the imprecation against `needless complexity'.

Upon packing his bags in preparation for a journey, the savvy traveller
discards fully fifty percent of his stowed possessions, for he realizes
that needless clutter and gratuitous baggage but weigh him down and
distract him from his goal. It is only after many years of repeated
mistakes that the truly seasoned traveller can a priori recognize
unjustifiable bloat for its hidden promise of inevitable annoyance.

--tom

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

For example, sort() on a large data set can take a swell spell

Sort is a good example. I remember an IBM rep doing a demo of a little APL
"portable" machine back in the early 70s which I immediately hung by typing
in the magic apl gibberish for​: "sort" "reverse" "0..50000"

It went away, and could not be interrupted. He finally had to power cycle it
rather than wait for the sort to finish (it was, obviously, not a speed
demon - I'm not entirely sure, but it may have been a 4004 chip running
a 360 emulator running 360 apl :-).

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

At 06​:59 AM 1/11/00 -0700, Tom Christiansen wrote​:

On Mon, 10 Jan 2000 13​:28​:16 -0800 (PST)
Larry Wall <larry@​wall.org> wrote
in <200001102128.NAA15919@​kiev.wall.org>​:

​:We need to delay sub invocations until we know we're in a safe state,
​:such as the beginning of a statement, or at the interator of any looping
​:constructs, including regular expressions.

What about slow-running ops? It seems like some of them require more
careful work than others.

What we'd need was a wedge into the long-running op at a safe place.
Basically the same code that'd get executed between ops (probably the exact
same code) just done within an op.

We could do this either with an explicit wedge (essentially a yield())
which feels icky, or with an implicit wedge, say in one of the SV
manipulating functions. We might want to have an explicit "interrupts
enable" flag so that the default is to not do this--dunno if it'd be safe
to drop into runops() in the middle of a regex for example.

That still gets us nowhere with potentially long running system calls,
unless there's some way to issue them asynchronously and explicitly wait
for their return, in which case we could treat it as a general event wait
and catch it the same way as we'd catch signals or other async events.

But what if it's in XS code? How will reliable signal delivery interact
with XS code?

Well, the wedge method would get us in for anything that didn't block, but
that may not be enough, and it may not be safe to be dropping into runops
from within an XS function anyway. Nobody writes these to be
reentrant-safe. (Though the number of cases where it actually matters is
relatively small)

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From @TimToady

Tom Christiansen writes​:
: On Mon, 10 Jan 2000 13​:28​:16 -0800 (PST)
: Larry Wall <larry@​wall.org> wrote
: in <200001102128.NAA15919@​kiev.wall.org>​:
:
: :We need to delay sub invocations until we know we're in a safe state,
: :such as the beginning of a statement, or at the interator of any looping
: :constructs, including regular expressions.
:
: What about slow-running ops? It seems like some of them require more
: careful work than others. For example, sort() on a large data set can
: take a swell spell, and readline() on a serial line or stream connection
: can take virtually infinite time. In the latter case, I suppose we have
: the EINTR and the SA_RESTART dodge. Here's my list of such operators​:
:
: sys related​: accept, close, connect, fcntl, flock, getc, ioctl,
: open, print, read, readline, recv, send, syscall,
: sysread, syswrite, wait, waitpid
:
: Those aren't that bad. It's the others that seem more challenging.
: For example​:
:
: indirect calls​: sort, map, grep

That's why I said, "at the iterator [un-sic] of any looping constructs."
I was counting those as looping constructs.

: Where do those take the signal? What if it's a built-in sorting, such as
: C<sort @​array>, or using the newly optimized built-ins (from perldelta​:
: ``Simple sort() using { $a <=> $b } and the like are optimized Many
: common sort() operations using a simple inlined block are now optimized
: for faster performance.'')?

The proper check point is probably in qsortsv(), which is used to call all
the other routines.

: What about system() and `backticks`? Are these part of the sys-related
: case above? Is glob() an issue? It uses many readdir()s, unless it's not
: built-in, in which case it will be using an external program. Does this
: fall into the system() and `backtick` case?

Any op of that sort can set a flag which says it's safe to call the sub
directly, as we do now.

: Is sleep() a sys-related case?

Can be solved with either as above or via EINTR.

: What about list-context flipflops? "a" .. "zzzzz" takes a long time
: (well, until you hit out of memory :-).

"at the iterator of any looping constructs"

: How about the dofile and require operators? Is it safe to permit
: receipt of the signal once they've compiled and once they're executing
: their newly compiled code? I assume that the import() component of
: the use operator would be signallable during its execution.

The iterator of the compiler is byacc.

: Finally, let's have some fun ones. What about tie() and its related
: intercepts? There's no reason to imagine that any of the TIE*() functions
: shall complete in "reasonable" (non-arbitrary) time. At what granularity
: should they be interruptible? Consider​:
:
: tie %mib, 'Tie​::SMTP', $remhost;
: $desc = $mib{ "system.sysDescr" };
:
: The tie itself might take a long time because $remhost is unreachable.
: If there's underlying Perl code that's stuck in one of the previously
: mentioned cases (e.g. connect), perhaps this suffices. Same situation
: with the tied()d call to FETCH() in the next line.

If it's tied to Perl code, that operates at the granularity of the Perl
code, as normal. A connect would be an EINTR or "sig_sub_is_safe = 1"
situation.

: But what if it's in XS code? How will reliable signal delivery interact
: with XS code?

Existing XS code is a problem regardless. Inventing a new minilanguage
does not solve this. We have the choice (or perhaps the user has the
choice) of whether frequent hanging or occasional core dumping is
the lesser of two evils. But there are at least three ways to ameliorate
this.

First, we can do the deliver-immediately-on-duplicate-signal trick.
That could be generalized to deliver immediately on any second signal if
sufficient time has passed, provided time() is a safe system call.

Second, we could interrupt ourselves periodically with an interval timer
on systems that support that, and deliver any sufficiently delayed signals
immediately.

Third, we could document how to install a check point, deal with EINTR,
set sig_sub_is_safe, etc. for the benefit of XS writers, in the
expectation that they'll do the right thing.

As far as I'm concerned, the main remaining issue is how to direct
signals to a particular thread. This seems to me to be an issue of
the check point code simply refusing to deliver a signal unless the
right thread is running (and of course making sure the signal thread
gets scheduled as soon as is reasonable). We might not be able to
honor sig_sub_is_safe under threaded code, but then all your blocking
operations should send you back to the scheduler anyway, so it
doesn't seem to be a big issue.

In short, this is all insane, but it's the sort of insanity we should
be protecting the Perl programmer from.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

:As far as I'm concerned, the main remaining issue is how to direct
:signals to a particular thread.

I never did manage to get signal delivery working under
Linux, which used pids for threads.

:In short, this is all insane, but it's the sort of insanity we should
:be protecting the Perl programmer from.

sigs :-)

--tom

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

At 11​:37 AM 1/11/00 -0700, Tom Christiansen wrote​:

​:As far as I'm concerned, the main remaining issue is how to direct
​:signals to a particular thread.

I never did manage to get signal delivery working under
Linux, which used pids for threads.

Signals and threads are going to be a persistent problem. It's anyone's
guess which thread gets an async signal, and even the sync signals that
ought to go to the thread that generated them often don't. (The POSIX
standard says they don't have to, IIRC)

Then Linux adds more fun to the mix, as it's only mostly POSIX-compliant,
and signals that ought to go to any thread instead only go to the thread
that triggered the signal in the first place. Very annoying if you're using
a single signal-handling thread. (Of course, if you stop assuming
LinuxThreads are POSIX compliant it's a lot easier, since the POSIX
assumptions don't get in the way. Pity they used the POSIX routine names,
which is just darned confusing)

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Tue, Jan 11, 2000 at 10​:31​:36AM -0800, Larry Wall wrote​:

Existing XS code is a problem regardless. Inventing a new minilanguage
does not solve this.

Of course immediate atomic delivery solves this, as well as removes
the complexity of intentional slowing-down of tight loops.

First, we can do the deliver-immediately-on-duplicate-signal trick.
That could be generalized to deliver immediately on any second signal if
sufficient time has passed, provided time() is a safe system call.

If this delivery is unsafe, then this is just putting things under the carpet.

As far as I'm concerned, the main remaining issue is how to direct
signals to a particular thread.

Let me repeat one of the reference points​: close to impossible under OS/2.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

Simon Cozens writes​:

And if you do not like the interface, write a module which
deparses

sub { ++$count; return }

to [ inc => \$count ]. Make assignment to $SIG autoload this module.
If deparse fails, enable the delayed samantic.

I hate to suggest this, but wouldn't
$SIG{FOO} = sub { ++$count; return }
be easier for all concerned?

Hmm, is not this what I proposed?

This seems wasteful​:
If you disallow running arbitary code, you're restricting people.

You cannot run arbitrary code in an immediate sighandler. If you
delay execution, you are restricting people.

If you allow\, say\, a \`\[code => sub \{ \.\.\. \}\]'\, everyone will use that

instead of the other `instructions', out of laziness.

Their lazyness is nothing of our concern.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

Tom Christiansen writes​:

Larry> That's more needless complexity.
Larry> This should be hidden from the user.

Ilya> And if you do not like the interface, write a module which
Ilya> deparses
Ilya> sub { ++$count; return }
Ilya> to [ inc => \$count ]. Make assignment to $SIG autoload this module.
Ilya> If deparse fails, enable the delayed semantic.

This still falls under the imprecation against `needless complexity'.

"This" is what? Needless for what?

Upon packing his bags in preparation for a journey, the savvy traveller
discards fully fifty percent of his stowed possessions, for he realizes
that needless clutter and gratuitous baggage but weigh him down and
distract him from his goal. It is only after many years of repeated
mistakes that the truly seasoned traveller can a priori recognize
unjustifiable bloat for its hidden promise of inevitable annoyance.

Hmm, is not it prose? Did anybody find any technical contents in this?

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From @TimToady

Ilya Zakharevich writes​:
: On Tue, Jan 11, 2000 at 10​:31​:36AM -0800, Larry Wall wrote​:
: > Existing XS code is a problem regardless. Inventing a new minilanguage
: > does not solve this.
:
: Of course immediate atomic delivery solves this, as well as removes
: the complexity of intentional slowing-down of tight loops.

But your delivery doesn't deliver, in the sense of guaranteeing the
script will notice the signal any time soon. My scheme is also does
atomic delivery, only not to Perl, but to a C array and a global, which
we then take pains to check periodically.

: > First, we can do the deliver-immediately-on-duplicate-signal trick.
: > That could be generalized to deliver immediately on any second signal if
: > sufficient time has passed, provided time() is a safe system call.
:
: If this delivery is unsafe, then this is just putting things under the carpet.

As I recall, you're the one who proposed immediate delivery on a second
signal not so very many messages ago.

: > As far as I'm concerned, the main remaining issue is how to direct
: > signals to a particular thread.
:
: Let me repeat one of the reference points​: close to impossible under OS/2.

Let me point out that we don't have to deliver C level signals to
another thread. We only have to deliver Perl level signals. My
proposal divorces the two. The C signal comes in on whatever thread
happens to be running at the time, and atomically sets up the Perl
signal. Then all other Perl threads simply ignore the signal until the
signal thread wakes up. At worst this depends on the latency of the
scheduler, and remains completely safe.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From @TimToady

Ilya Zakharevich writes​:
: Simon Cozens writes​:
: > >And if you do not like the interface, write a module which
: > >deparses
: > >
: > > sub { ++$count; return }
: > >
: > >to [ inc => \$count ]. Make assignment to $SIG autoload this module.
: > >If deparse fails, enable the delayed samantic.
: >
: > I hate to suggest this, but wouldn't
: > $SIG{FOO} = sub { ++$count; return }
: > be easier for all concerned?
:
: Hmm, is not this what I proposed?

Yes, and it's still relatively useless in the overall scheme of things.
The purpose of a signal is to force the scheduler to run some meaningful
code. Just because C prevents this doesn't mean we can't fake it in Perl.

: > This seems wasteful​:
: > If you disallow running arbitary code, you're restricting people.
:
: You cannot run arbitrary code in an immediate sighandler. If you
: delay execution, you are restricting people.

We can make that restriction relatively insignificant.

: > If you allow, say, a `[code => sub { ... }]', everyone will use that
: > instead of the other `instructions', out of laziness.
:
: Their lazyness is nothing of our concern.

You mean, their laziness is nothing of *your* concern. It is certainly
my concern. That's just one of the things a language designer has to
take into account.

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Tue, Jan 11, 2000 at 01​:03​:04PM -0800, Larry Wall wrote​:

: > Existing XS code is a problem regardless. Inventing a new minilanguage
: > does not solve this.
:
: Of course immediate atomic delivery solves this, as well as removes
: the complexity of intentional slowing-down of tight loops.

But your delivery doesn't deliver, in the sense of guaranteeing the
script will notice the signal any time soon. My scheme is also does
atomic delivery, only not to Perl, but to a C array and a global, which
we then take pains to check periodically.

It is good that our schemes are so close. But mine is better ;-)​: you
do not need to check things periodically.

First I failed to see how your scheme will make script notice the signal.
Later I realized that you probably you mean die() here​:

  $SIG{} = [die => $message];

will die atomically, but may leave things in a non-consistent state.
This is indeed a questionable behaviour. What are other things people
want to do in a sighandler?

  a) set a variable;
  b) increment a variable;
  c) exit();
  d) wait() and assign the result;
  e) wait() and append the result to an array/hash;
  f) die with a message;

All things in a)..d) can be made atomically without any damage. e)
can be done atomically if the array/hash is tied to something which
allows an atomic update. This leaves 'f', which is much better in
your setup.

So question is​: are we going to make a major rewrite just to allow
really-safe die() in a signal handler?

: Let me repeat one of the reference points​: close to impossible under OS/2.

Let me point out that we don't have to deliver C level signals to
another thread. We only have to deliver Perl level signals.

Not a tiny bit easier​: you still need to unblock the thread.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Tue, Jan 11, 2000 at 01​:11​:11PM -0800, Larry Wall wrote​:

: Their lazyness is nothing of our concern.

You mean, their laziness is nothing of *your* concern. It is certainly
my concern. That's just one of the things a language designer has to
take into account.

Hmm, is it the reason why now *by default* h2xs produces almost
unusable code? [Well, *now* it does not produce anything, I meant the
state things may boil down to.] ;-)

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

Ilya Zakharevich wrote​:

Simon Cozens writes​:

    If you allow\, say\, a \`\[code => sub \{ \.\.\. \}\]'\, everyone will use that

instead of the other `instructions', out of laziness.

Their lazyness is nothing of our concern.

hm, and I thought laziness was one of the three great vitues of a programmer.
maybe that was something I read in the Python manual...

maybe I'm being hubristic.

Greg

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Tue, Jan 11, 2000 at 04​:35​:27PM -0500, london@​pixelmagic.com wrote​:

Their lazyness is nothing of our concern.

hm, and I thought laziness was one of the three great vitues of a programmer.

It is a virtue of a programmer, but not in *another* programmer. ;-)

An attempt to grant lazyness to signal-handler's programmers is
laudable in general. But if the price is significant obfuscation of
the code base, slowing things down, and unusability in present of
XSUBs, things start to look very different.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

At 04​:19 PM 1/11/00 -0500, Ilya Zakharevich wrote​:

This is indeed a questionable behaviour. What are other things people
want to do in a sighandler?

a) set a variable;
b) increment a variable;
c) exit();
d) wait() and assign the result;
e) wait() and append the result to an array/hash;
f) die with a message;

g) Queue up another I/O request
h) Update a Tk display
i) Send a syslog message
j) Close one file on a filehandle and open another

You're letting the crippled signal implementation limit you.

: Let me repeat one of the reference points​: close to impossible under
OS/2.

Let me point out that we don't have to deliver C level signals to
another thread. We only have to deliver Perl level signals.

Not a tiny bit easier​: you still need to unblock the thread.

So? Unless the thread is waiting on a blocking system call it's not a big
deal. The thread's cond_waiting and you signal it.

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From [Unknown Contact. See original ticket]

On Tue, Jan 11, 2000 at 04​:32​:46PM -0500, Dan Sugalski wrote​:

At 04​:19 PM 1/11/00 -0500, Ilya Zakharevich wrote​:

This is indeed a questionable behaviour. What are other things people
want to do in a sighandler?

a) set a variable;
b) increment a variable;
c) exit();
d) wait() and assign the result;
e) wait() and append the result to an array/hash;
f) die with a message;

g) Queue up another I/O request
h) Update a Tk display
i) Send a syslog message
j) Close one file on a filehandle and open another

If die() were safe, all these would easy to implement...

: Let me repeat one of the reference points​: close to impossible under
OS/2.

Let me point out that we don't have to deliver C level signals to
another thread. We only have to deliver Perl level signals.

Not a tiny bit easier​: you still need to unblock the thread.

So? Unless the thread is waiting on a blocking system call it's not a big
deal.

Why do you thing it is not going to be waiting on a blocking system
call most of the time? For many threading paradigms this is exactly
what happens.

The thread's cond_waiting and you signal it.

What made you thingk cond_wait() is not a blocking system call?

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 11, 2000

From @TimToady

Ilya Zakharevich writes​:
: On Tue, Jan 11, 2000 at 01​:03​:04PM -0800, Larry Wall wrote​:
: > : > Existing XS code is a problem regardless. Inventing a new minilanguage
: > : > does not solve this.
: > :
: > : Of course immediate atomic delivery solves this, as well as removes
: > : the complexity of intentional slowing-down of tight loops.
: >
: > But your delivery doesn't deliver, in the sense of guaranteeing the
: > script will notice the signal any time soon. My scheme is also does
: > atomic delivery, only not to Perl, but to a C array and a global, which
: > we then take pains to check periodically.
:
: It is good that our schemes are so close. But mine is better ;-)​: you
: do not need to check things periodically.

Only for some values of "you". If you increment a variable then some
value of "you" has to write code to check the variable. In my proposal
Perl checks it for you.

: First I failed to see how your scheme will make script notice the signal.
: Later I realized that you probably you mean die() here​:
:
: $SIG{} = [die => $message];
:
: will die atomically, but may leave things in a non-consistent state.

Eh? I never said anything like that...

: This is indeed a questionable behaviour. What are other things people
: want to do in a sighandler?
:
: a) set a variable;

Forcing the script to check the variable periodically.

: b) increment a variable;

Forcing the script to check the variable periodically.

: c) exit();

Can be optimized away as a subroutine with a known constant value. :-)

: d) wait() and assign the result;

Again, somebody's gotta check for the result explicitly if they care.

: e) wait() and append the result to an array/hash;
: f) die with a message;

: All things in a)..d) can be made atomically without any damage. e)
: can be done atomically if the array/hash is tied to something which
: allows an atomic update.

Seems unlikely, since you probably have to allow malloc in there somewhere
to grow the array, unless you're journaling to disk, which seems relatively
useless, or allocate a fixed size array, which can drop signals.

: This leaves 'f', which is much better in your setup.

And you left out​:

  g) anything else you might want to do safely in a signal handler.

: So question is​: are we going to make a major rewrite just to allow
: really-safe die() in a signal handler?

I don't think it's a major rewrite.

All we have to do is make sure our check points can reach a consistent
state if they need to. So the check point in sort may have to switch
stacks, for instance.

: > : Let me repeat one of the reference points​: close to impossible under OS/2.
: >
: > Let me point out that we don't have to deliver C level signals to
: > another thread. We only have to deliver Perl level signals.
:
: Not a tiny bit easier​: you still need to unblock the thread.

How does OS/2 unblock a thread? Obviously it can, or threads would never
run. How about if the signal-handling thread is waiting on some I/O that
another thread can provide?

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 09​:28 PM 1/11/00 -0500, Ilya Zakharevich wrote​:

On Tue, Jan 11, 2000 at 05​:22​:20PM -0500, Dan Sugalski wrote​:

Why do you thing it is not going to be waiting on a blocking system
call most of the time? For many threading paradigms this is exactly
what happens.

So we have sync system calls instead spawn off a thread to do the call
while the spawning thread cond_waits on something. To wake the thread you
kill the thread doing the syscall and pop a cond_signal to the waiting
thread. There are other ways, too, of course.

You still think that you can wake something which cond_wait()s from
another thread. And you make things extremely complicated and
extremely unefficient.

Yes I do, and no it isn't. Perl code does a cond_wait. The cond_wait code
stores the condition in the thread structure and waits. Something needs to
wake the thread, so it sets the condition and wakes it. No Big Deal.

And yes, a new thread for long syscalls is inefficient. (And a completely
different topic than cond_waits) Thread pools make it cheaper (or at least
amortize the costs) and if the call is likely to block for a while anyway
the real expense is essentially non-existant.

What made you thingk cond_wait() is not a blocking system call?

What makes you think the cond_wait that I'm thinking of is the one you're
thinking of? And what makes you think I'm not considering tracking the
condition and signalling it?

Waking *all* the thread which wait on this?

Yeah, and....? The underlying code for the other threads (assuming that
other threads are even waiting on the same thing) see the condition wasn't
for them and re-wait. Spurious wakeups are a part of life, aren't that
common, and handling them is cheap.

Yes, it does mean a bit of extra code in the core, but it's not code that's
in any sort of critical performance path.

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 10​:18​:24AM -0500, dan@​sidhe.org wrote​:

At 09​:54 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

I usually give up at this point because I can see that signals are a
mess and getting them to work with multiple threads is going to make it
worse. I am encouraged to hear that linux does not follow POSIX. My
experience with POSIX threads has not been very encouraging.

I wouldn't get too encouraged. Linux threads are an attempt to shoehorn
POSIX threads onto a system that actively disapproves of them. The big
issues are signals and process table exhaustion, but there are other niggly
things. (Each thread has a separate pid, for example, and the kernel
doesn't really know what 'process' a thread belongs to)

So what? I know (from kernel traffic) they are aware of and fixing the
process table exhaustion...

My
unsubstantiated suspicion is that the POSIX thread spec was written well
ahead of any working implementation. I think it is likely that the linux
model is better even though I haven't checked myself. This is just a
vague feeling. I might be completely backwards here.

In some ways its worse. Because threads are really separate processes,

What's the difference? Memory sharing is the same, right?

only the thread that actually gets the signal delivered can see it.

Yes. That's one of the reasons I felt that linux might be an
improvement over the POSIX mess.

Not
necessarily a bad thing (though it makes separate signal-handling threads
trickier)

I never understood the alure of routing all the signals to a single
signal-handling thread. Can anyone comment on this?

but it is in direct contradiction to the standard they're
implementing.

True.

(And for all its limits, POSIX threads were designed by a
bunch of experienced, clever guys who got a standard that managed to meet
the requirements of the folks involved. I'm not sure that the Linux changes
have that level of experience behind their changes)

As seen from here, that doesn't sound conclusive one way or the other.

--
"Never ascribe to malice that which can be explained by stupidity."
  via, but not speaking for Deutsche Bank

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 10​:35 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

On Wed, Jan 12, 2000 at 10​:18​:24AM -0500, dan@​sidhe.org wrote​:

At 09​:54 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

I usually give up at this point because I can see that signals are a
mess and getting them to work with multiple threads is going to make it
worse. I am encouraged to hear that linux does not follow POSIX. My
experience with POSIX threads has not been very encouraging.

I wouldn't get too encouraged. Linux threads are an attempt to shoehorn
POSIX threads onto a system that actively disapproves of them. The big
issues are signals and process table exhaustion, but there are other
niggly
things. (Each thread has a separate pid, for example, and the kernel
doesn't really know what 'process' a thread belongs to)

So what? I know (from kernel traffic) they are aware of and fixing the
process table exhaustion...

Good. I hadn't seen that, but I only skim the weekly summaries occasionally.

My
unsubstantiated suspicion is that the POSIX thread spec was written well
ahead of any working implementation. I think it is likely that the linux
model is better even though I haven't checked myself. This is just a
vague feeling. I might be completely backwards here.

In some ways its worse. Because threads are really separate processes,

What's the difference? Memory sharing is the same, right?

Yes, though there's more to a thread than memory sharing. (You can
currently flock yourself into a deadlock too, FWIW, though hopefully
they're fixing that, too)

only the thread that actually gets the signal delivered can see it.

Yes. That's one of the reasons I felt that linux might be an
improvement over the POSIX mess.

In some ways it is, for the synchronous signals--they're more installed
error handlers than anything else. Async signals, on the other hand, are
events rather than errors, and are delivered to the *process*, not to the
thread. Who should get SIGHUP, or SIGCHLD, or SIGCONT, or SIGIO? These all
deal with process-level events, and the thread that was responsible for
them being generated (if you can even figure that out easily) isn't
necessarily going to be the one that should handle them.

Not
necessarily a bad thing (though it makes separate signal-handling threads
trickier)

I never understood the alure of routing all the signals to a single
signal-handling thread. Can anyone comment on this?

It makes handling the event signals easier. You just route 'em all to a
single thread that deals with them, rather than having to cope with them in
all your threads.

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From @TimToady

Fisher Mark writes​:
: (Hmmm. I wonder what would be the performance of a text editor written in
: Perl?)

Depends on how you implement your character insertion, your screen
refresh, and your various incestuous internal hooks. But mostly it
depends on whether you call it pim or pemacs. :-)

Larry

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 10​:56​:06AM -0500, dan@​sidhe.org wrote​:

At 10​:35 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

On Wed, Jan 12, 2000 at 10​:18​:24AM -0500, dan@​sidhe.org wrote​:

In some ways its worse. Because threads are really separate processes,

What's the difference? Memory sharing is the same, right?

Yes, though there's more to a thread than memory sharing. (You can
currently flock yourself into a deadlock too, FWIW, though hopefully
they're fixing that, too)

Yah, they're definitely aware of that.

only the thread that actually gets the signal delivered can see it.

Yes. That's one of the reasons I felt that linux might be an
improvement over the POSIX mess.

In some ways it is, for the synchronous signals--they're more installed
error handlers than anything else. Async signals, on the other hand, are
events rather than errors, and are delivered to the *process*, not to the
thread. Who should get SIGHUP, or SIGCHLD, or SIGCONT, or SIGIO? These all
deal with process-level events, and the thread that was responsible for
them being generated (if you can even figure that out easily) isn't
necessarily going to be the one that should handle them.

I don't know. At least the control is in the hands of the developer. On
the other hand, perhaps POSIX provides this as an option too. I am
hardly qualified to debate this stuff.

I never understood the alure of routing all the signals to a single
signal-handling thread. Can anyone comment on this?

It makes handling the event signals easier. You just route 'em all to a
single thread that deals with them, rather than having to cope with them in
all your threads.

I'm still mystified. Obviously the library/kernel can do this
automatically but what is so hard about doing it at the application
level? Wouldn't it just be a matter of adding a bunch of handlers
to the children threads​:

  static Signal_t process_sighandler(int sig) { kill(ParentPID, sig); }

Am I missing something?

--
"Never ascribe to malice that which can be explained by stupidity."
  via, but not speaking for Deutsche Bank

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 11​:17 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

On Wed, Jan 12, 2000 at 10​:56​:06AM -0500, dan@​sidhe.org wrote​:

At 10​:35 AM 1/12/00 -0500, Joshua N Pritikin wrote​:

only the thread that actually gets the signal delivered can see it.

Yes. That's one of the reasons I felt that linux might be an
improvement over the POSIX mess.

In some ways it is, for the synchronous signals--they're more installed
error handlers than anything else. Async signals, on the other hand, are
events rather than errors, and are delivered to the *process*, not to the
thread. Who should get SIGHUP, or SIGCHLD, or SIGCONT, or SIGIO? These all
deal with process-level events, and the thread that was responsible for
them being generated (if you can even figure that out easily) isn't
necessarily going to be the one that should handle them.

I don't know. At least the control is in the hands of the developer. On
the other hand, perhaps POSIX provides this as an option too. I am
hardly qualified to debate this stuff.

Well, POSIX doesn't, really. More to the point it explicitly makes the
"what thread gets a signal" implementation-defined. So what Linux is doing
is mostly OK, except it's my understanding that signals are supposed to
roll over--if they get popped to a thread that's blocked that particular
signal then the signal isn't supposed to be lost, instead sent to another
thread.

I think part of this is to accommodate those systems that use a LWP/Kernel
thread scheme--the signal goes to the process/KT and gets delivered to the
first thread that runs on that process/KT that's set itself to handle the
signal.

POSIX threads are a sort of cross-platform compromise. Not 100% great, but
workable on a wide range of OS/platform setups. Which does mean that Linux
can do it better since it's a private implementation, but the problem is
they fib and say they're POSIX (and thus you'd expect them to behave in the
POSIX manner) but they really aren't.

I never understood the alure of routing all the signals to a single
signal-handling thread. Can anyone comment on this?

It makes handling the event signals easier. You just route 'em all to a
single thread that deals with them, rather than having to cope with
them in
all your threads.

I'm still mystified. Obviously the library/kernel can do this
automatically but what is so hard about doing it at the application
level? Wouldn't it just be a matter of adding a bunch of handlers
to the children threads​:

static Signal_t process_sighandler(int sig) { kill(ParentPID, sig); }

Am I missing something?

Nope. But that's error prone and, more to the point, platform-specific in a
way it shouldn't be if it's really POSIX threads. (And I'm not sure that
the parent pid's set right, but you can always set the signal thread pid in
a global somewhere and work with that)

Not that we can't (or shouldn't) deal with it at the perl level, of course.
Just an annoyance.

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

Larry Wall wrote​:

Fisher Mark writes​:
: (Hmmm. I wonder what would be the performance of a text editor written in
: Perl?)

Depends on how you implement your character insertion, your screen
refresh, and your various incestuous internal hooks. But mostly it
depends on whether you call it pim or pemacs. :-)

actually, its called "gedi" and should be rolled into the Tk800.017 release.
(if not, I think its in the widget demo) most of it is perl subs that Nick and I
scrunched into Tk​::Text and Tk​::TextUndo. It has all the functionality of the
textedit program on unix.

ok, ok, a lot of the underlying code is C (character inserts, and the like)
but, a lot of the higher level stuff is pure perl. (search and replace, undo/redo, etc)
never benchmarked it though...

Greg

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 10​:20​:18AM -0500, Dan Sugalski wrote​:

At 09​:24 PM 1/11/00 -0500, Ilya Zakharevich wrote​:

But since safe signals are not possible (see XSUBs), and require a
significant rewrite of the most important "do a lot" Perl opcodes (at
any checkpoint we should be ready for a longjump), this is still
rather moot.

Safe immediate signal handlers in perl aren't possible.

As I demonstrated, they are for a large (though not enormous) subset
of things people want to do in signal handlers.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 02​:49 PM 1/12/00 -0500, Ilya Zakharevich wrote​:

On Wed, Jan 12, 2000 at 10​:20​:18AM -0500, Dan Sugalski wrote​:

At 09​:24 PM 1/11/00 -0500, Ilya Zakharevich wrote​:

But since safe signals are not possible (see XSUBs), and require a
significant rewrite of the most important "do a lot" Perl opcodes (at
any checkpoint we should be ready for a longjump), this is still
rather moot.

Safe immediate signal handlers in perl aren't possible.

As I demonstrated, they are for a large (though not enormous) subset
of things people want to do in signal handlers.

s/want to do/think they're limited to doing/;

Coming from a platform with very strong asynchronous leanings (VMS), it's
been my experience that people with a mainly Unix or Unix-inspired
background just don't expect a whole lot from their async sub-system.
Probably because signals are so terribly limited and the only other
experiences they have are with X and, well, the less said the better... :)

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 10​:28​:40AM -0500, Dan Sugalski wrote​:

You still think that you can wake something which cond_wait()s from
another thread. And you make things extremely complicated and
extremely unefficient.

Yes I do, and no it isn't. Perl code does a cond_wait. The cond_wait code
stores the condition in the thread structure and waits. Something needs to
wake the thread, so it sets the condition and wakes it. No Big Deal.

If it were correct, sure. But it is not. This will not "wake it", it
will wake all the threads which wait on this condition. So some more
work is needed.

And yes, a new thread for long syscalls is inefficient. (And a completely
different topic than cond_waits)

Then why did you mention cond_waits?

Thread pools make it cheaper (or at least
amortize the costs) and if the call is likely to block for a while anyway
the real expense is essentially non-existant.

How would you know whether it is likely to do it or not? This is the
whole point of threads that you do not need to know this, and still
can write effecient programs.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 03​:06​:16PM -0500, Dan Sugalski wrote​:

As I demonstrated, they are for a large (though not enormous) subset
of things people want to do in signal handlers.

s/want to do/think they're limited to doing/;

Coming from a platform with very strong asynchronous leanings (VMS).

OS/2 also might have a nice System Exception model, but this still
does not work well in a presence of CRTL. Can you use CRT calls in
this model?

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 04​:07 PM 1/12/00 -0500, Ilya Zakharevich wrote​:

On Wed, Jan 12, 2000 at 03​:06​:16PM -0500, Dan Sugalski wrote​:

As I demonstrated, they are for a large (though not enormous) subset
of things people want to do in signal handlers.

s/want to do/think they're limited to doing/;

Coming from a platform with very strong asynchronous leanings (VMS).

OS/2 also might have a nice System Exception model, but this still
does not work well in a presence of CRTL. Can you use CRT calls in
this model?

Which model, VMS' asyc system? Sure, some of them. There are limits to
what's acceptable, but the limits are pretty broad. Generally you're not
using the C RTL that much in an AST handler--most of the interesting work's
done with system services. (But, then, VMS has a very rich set of system
services, so it's not a problem)

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 04​:19​:26PM -0500, Dan Sugalski wrote​:

Which model, VMS' asyc system? Sure, some of them. There are limits to
what's acceptable, but the limits are pretty broad. Generally you're not
using the C RTL that much in an AST handler--most of the interesting work's
done with system services. (But, then, VMS has a very rich set of system
services, so it's not a problem)

Which is basically the same as with OS/2​: you cannot use any
"interesting" CRT call, and need to go into the "non-portable" mode.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

At 04​:22 PM 1/12/00 -0500, Ilya Zakharevich wrote​:

On Wed, Jan 12, 2000 at 04​:19​:26PM -0500, Dan Sugalski wrote​:

Which model, VMS' asyc system? Sure, some of them. There are limits to
what's acceptable, but the limits are pretty broad. Generally you're not
using the C RTL that much in an AST handler--most of the interesting
work's
done with system services. (But, then, VMS has a very rich set of system
services, so it's not a problem)

Which is basically the same as with OS/2​: you cannot use any
"interesting" CRT call, and need to go into the "non-portable" mode.

Yeah, but there really aren't any "interesting" CRTL calls. (Well, except
in the nastiest sense of the word interesting, and those calls are best
left alone anyway)

Not that this really matters for perl, since the signal handlers won't be
executing at interrupt time anyway...

  Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
dan@​sidhe.org have teddy bears and even
  teddy bears get drunk

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

Ilya Zakharevich (lists.p5p)​:

It is a virtue of a programmer, but not in *another* programmer. ;-)

In short, you wish to deny other people the chance to be virtuous? :)

--
Preudhomme's Law of Window Cleaning​:
  It's on the other side.

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

Simon Cozens writes​:

Ilya Zakharevich (lists.p5p)​:

It is a virtue of a programmer, but not in *another* programmer. ;-)

In short, you wish to deny other people the chance to be virtuous? :)

Do you imply that virtuousness is always a kind of lazyness?

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From @chipdude

According to Ilya Zakharevich​:

You can put Hanukka bush ornaments on anything. Most of the time
the only reason Moliere syndrom appears is to hide the fact that the
message is content-free. Even if not, things may improve by
removing ornaments.

Your point is well-taken.

On the other hand, good design often comes down to taste and
intuition, which usually don't survive reductionist analysis.

Sometimes the only available alternative to being vague and indirect
is leaving important things unsaid. Which is worse?
--
Chip Salzenberg - a.k.a. - <chip@​valinux.com>
  "He's Mr. Big of 'Big And Tall' fame." // MST3K

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

On Wed, Jan 12, 2000 at 02​:22​:30PM -0800, Chip Salzenberg wrote​:

You can put Hanukka bush ornaments on anything. Most of the time
the only reason Moliere syndrom appears is to hide the fact that the
message is content-free. Even if not, things may improve by
removing ornaments.

Your point is well-taken.

On the other hand, good design often comes down to taste and
intuition, which usually don't survive reductionist analysis.

Sometimes the only available alternative to being vague and indirect
is leaving important things unsaid. Which is worse?

Nobody will argue the role of metaphores and friends as vehicles of
communication. I was considering situations when all that rides this
channel is nil, or when the communication could have been performed as
well without these clutches.

Most of the time it boils down to the question of taste, which is
probably out of the realm of this particular forum.

Ilya

@p5pRT
Copy link
Author

p5pRT commented Jan 12, 2000

From [Unknown Contact. See original ticket]

Most of the time it boils down to the question of taste, which is
probably out of the realm of this particular forum.

You're overreaching there. Taste certainly *does* count, and it
counts in this forum as much as in any--perhaps more so even,
sometimes. Good programming, you see, really is as much an art as
it is a science or technical discipline--especially when it comes
to matters of design, which I believe was the topic in question.
Careful attention to human factors is indispensable.

Oh, taste might not count so much for all people at all times, but
it certainly does count here some of the time, depending perhaps
on who you are--by which I mean depending upon what you're trying
to do. You might say that it's merely a matter of "taste" and
therefore "out of bounds" that one should make a judgment call
regarding complexity. You like complexity; that's your preference.
I don't think it's a good thing, and that's *my* preference (even
though it's a design sin I myself am somewhat prone to falling
into).

Now if you go look at Perl, you'll see that shirking complexity and
sweeping the horrors out from under the compiler's domain and into
the poor programmer's cubicle--as you appear wont to do--is contrary
to *Perl's* preference. So, no, I certainly don't believe taste
in clarity and simplicity of design is out of bounds.

In particular, when Larry himself is the one deciding that some
proposed approach is too complicated to be added to Perl, even
though this is merely based upon his taste then it most certainly
*does* lie within the proper purview of this forum. After all, it
was his taste that got us where we are today. So yes, taste certainly
does count, especially when you're Larry. I hope that it counts
for the rest of us, too, because if we disdain to consider taste,
then surely Perl's own taste will become unpleasant to the tongue.

Left to ourselves, Ilya, neither you nor I am ever going to create
anything a tenth as nice as Perl. That's because both of us like
things that are just too complicated to be useful and popular by
the simple folk who get so much out of Perl. Although I harbor
some hope that I fall into a complexity zone an order of magnitude
simpler when compared to your own idiosyncratically tortuous
predilections, even so, let me be the first to admit how often I
miss the shortest and most diagonal route until this should be
pointed out to me. But at least when this simple path *is* illuminated
(sometimes in conjunction with a virtual cuff to the head to make
me see the light), I'm more than happy to walk it. I wish it were
likewise with you, but I don't know how you'll ever overcome your
own nature to complexify.

While I have your attention, thank you very much for your misplaced
attempt to condemn my writing as "mere prose". I cheerfully embrace
your would-be term of disrespect and convert it instead into a matter
of pride. Prose, you see, is something I rather like; I enjoy
writing prose, and I very much enjoy reading it. So I shall bear
your accusation of prose not as a scarlet letter of shame upon my
breast, but as the shining badge of honor I have chosen to make it.
After all, without prose, I would be left to write only equations,
which would annoy me to write, or else to write only poetry, which
would annoy you even more to read than it would me to write.

Since you were apparently unable or unwilling to understand my point
as it was delicately put to you previously, clad as it was in gentle
allegory to avoid damaging your feelings with so direct a statement
as you are now about to read, let me this time be perfectly clear.
What I was saying was simply that you yourself tend strongly toward
overdesign in the "way too darned complicated" way, and that you
should at every possible turn resist this temptation, lest Perl be
made into something fit for use only by those few others in the
world afflicted with your own peculiar penchant for complexity.

--tom

  "Make is like Pascal. Everyone likes it so much they can't
  resist changing it." --Dennis

@p5pRT
Copy link
Author

p5pRT commented Jan 13, 2000

From [Unknown Contact. See original ticket]

It's not that easy. Any significant task will require some complexity.
One of the primary tasks of the designer is to squish the complexity
around, not only trying to reduce the total complexity but also shifting
the complexity to the most painless area. The globally optimal solution
may have more total complexity, if such a thing could be measured,
because the complexity is forced into less harmful areas. In a
client/server situation, typically you want to pile more complexity onto
the server when it saves the clients some trouble, partly because there
are more clients than servers (and each client is implemented
independently), and partly because servers tend to run on beefier
hardware (complexity and performance tend to be inversely correlated.)

I don't think Ilya is enamored of complexity, I just think that he
weights things differently. He'd rather remove odd special cases that
make the perl implementation and documentation more complex, and add
features that allow users to get their jobs done more straightforwardly;
TomC would rather place more of the complexity burden of backwards
compatibility on the perl core and make life simpler for people who know
the existing perl and have written thousands of working scripts. From
either's perspective, the other seems to be a mad lunatic bent on
destroying perl for some strange diabolical and egomaniacal purpose. The
rest of us know they're both right, but that somehow the combination
results in a perl that just gets better and better, and only rarely
worse.

- Your resident anthropologist

If I have offended anyone by the above characterizations, I do most
humbly and deeply apologi... nah, screw it, neither of you knows where I
live.

@p5pRT
Copy link
Author

p5pRT commented Jan 16, 2000

From [Unknown Contact. See original ticket]

Joshua N Pritikin <joshua.pritikin@​db.com> writes​:

On Wed, Jan 12, 2000 at 11​:01​:16AM +0000, Tim.Bunce@​ig.co.uk wrote​:

My (vague) impression is that that work fragmented with one group adding
features and others being unhappy that there were too many features.
I think it's lost direction and consensus support. Sadly.

That's news to me. Granted, there was heated discussion for a few
months but I believe most folks are now mostly satisfied with the design
and implementation. Graham, Nick, Gisle and others, feel free to
correct me or forever hold your peace. ;-)

I am in both camps - on the one hand it is my _impression_ that Event
needs more functionality before I can use it to replace the Tcl event C
code that is at the core of perl/Tk. On the other hand I feel that
what we have is over complex. But I have not actually tried to
use Event in anger yet so it is not really fair to judge.

Furthermore, Event tries
to ignore the implications of multiple threads as much as possible.

Which is a weakness. Modern Tcl/Tk can at least "tolerate" multiple threads.
(Multiple threads are almost mandatory as work-rounds to Win32 issues.)
Thus Event should probably use the C level mutex stuff from the perl core
where appropriate. That said until thread support in the core settles
down I can understand Joshua's reluctance to mess with threads.

I have little idea about Win32.

Which is another weakness. If Event offered a solution to perl/Tk's Win32
woes I would be much more motivated to use it.

Personally, I am not interested in
doing a port. No volunteer has stepped forward so perhaps we can strike
a deal with Microsoft to commission the work. At least I can parrot
from those more knowledgable that the Win32 model is *significant*
different than Unix.

It may be so different that the current abstractions make no sense.

I think we have a nasty case of chicken-and-egg here​:

Event is not finished till it can do Win32.
Cannot do Win32 without threads.
Threads seem to need Event ...

Thus I suspect that what it really needs is ActiveState (e.g. Sarathy),
to need something working ...

--
Nick Ing-Simmons

@p5pRT
Copy link
Author

p5pRT commented Jan 16, 2000

From [Unknown Contact. See original ticket]

Larry Wall <larry@​wall.org> writes​:

Fisher Mark writes​:
​: (Hmmm. I wonder what would be the performance of a text editor written in
​: Perl?)

Depends on how you implement your character insertion, your screen
refresh, and your various incestuous internal hooks. But mostly it
depends on whether you call it pim or pemacs. :-)

The main drawback of ptked is the load time ;-)

--
Nick Ing-Simmons

@p5pRT
Copy link
Author

p5pRT commented Jan 16, 2000

From @gsar

On Sun, 16 Jan 2000 15​:37​:16 GMT, Nick Ing-Simmons wrote​:

Personally, I am not interested in
doing a port. No volunteer has stepped forward so perhaps we can strike
a deal with Microsoft to commission the work. At least I can parrot
from those more knowledgable that the Win32 model is *significant*
different than Unix.

It may be so different that the current abstractions make no sense.

I think we have a nasty case of chicken-and-egg here​:

Event is not finished till it can do Win32.
Cannot do Win32 without threads.
Threads seem to need Event ...

Thus I suspect that what it really needs is ActiveState (e.g. Sarathy),
to need something working ...

I haven't had time to do anything serious with the Event stuff, but
another thing that needs to happen before Windows can do Event-like
things properly is to rewrite the CRT abstraction layer (or at least
the parts that go into a wait state) to make them capable of
nonblocking waits/asynchronous events.

Let's keep this on the agenda for the 5.7.x development series.

Sarathy
gsar@​ActiveState.com

@p5pRT
Copy link
Author

p5pRT commented Jan 19, 2000

From [Unknown Contact. See original ticket]

On Sun, Jan 16, 2000 at 03​:37​:16PM +0000, nick@​ing-simmons.net wrote​:

Joshua N Pritikin <joshua.pritikin@​db.com> writes​:

Furthermore, Event tries
to ignore the implications of multiple threads as much as possible.

Which is a weakness. Modern Tcl/Tk can at least "tolerate" multiple threads.
(Multiple threads are almost mandatory as work-rounds to Win32 issues.)
Thus Event should probably use the C level mutex stuff from the perl core
where appropriate. That said until thread support in the core settles
down I can understand Joshua's reluctance to mess with threads.

Yes, that is the situation. I am happy to add whatever thread support
is deemed appropriate as soon as what is appropriate isn't a wildly
moving target.

--
"Never ascribe to malice that which can be explained by stupidity."
  via, but not speaking for Deutsche Bank

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant