SlideShare a Scribd company logo
Unix Programming with Perl 2 DeNA Co., Ltd. Kazuho Oku
Writing correct code tests aren’t enough tests don’t ensure that the code is correct writing correct code requires… knowledge of perl  and  knowledge of the OS Oct 15 2011 Unix Programming with Perl 2
Last Year’s Talk Covered these aspects of Unix programming using Perl $! and Errno how to evaluate the errors file handles their internals interaction w. fork(2) Unix signals various signals and how to handle them writing cancellable code Oct 15 2011 Unix Programming with Perl 2
Last Year’s Slides http://www.slideshare.net/kazuho/unix-programming-with-perl Oct 15 2011 Unix Programming with Perl 2
Today’s Talk will cover more advanced topics inter-process communication Unix signals and race condition Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock # check syntax errors in perl scripts by using perl –c my @cmd = ( $^X, (map { "-I$_" } grep { !ref $_ } @INC), '-c', $file, ); my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file);  http://d.hatena.ne.jp/tokuhirom/20100813/1281666615 Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} A1. blocks if the child process reads from STDIN Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock Close STDIN of the child before calling waitpid my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cin; while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} A1. blocks if the child process reads from STDIN A2. blocks if the child process writes long data to STDOUT or STDERR Oct 15 2011 Unix Programming with Perl 2
Size of the pipe buffer Pipe has size limit cannot write infinitely unless the other peer reads from pipe But actually, how large is the size limit? Oct 15 2011 Unix Programming with Perl 2
Size of the pipe buffer (2) Checking the size of the pipe buffer for (my $sz = 1; ; $sz++) { my @cmd = ( $^X, '-e', qq(print "1"x$sz), ); my $pid = open3(my $cin, my $cout, 0, @cmd) or die $!; while (waitpid($pid, 0) != $pid) {} print "size: $sz\n"; } Oct 15 2011 Unix Programming with Perl 2
Size of the pipe buffer (3) Size of the pipe buffer was… Linux 2.6.32 (x86-64): 65,536 bytes Mac OS X 10.6: 16,384 bytes Size may vary old versions of Linux: 4,096 bytes TCP streams and Unix sockets have configurable buffer size as well Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock How should we avoid deadlocks? if we do not need the output of the child process (ex. perl –c), could this be the right answer? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cout; close $cerr; while (waitpid($pid, 0) != $pid) {} ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file); Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock No. The child process  may  get killed while trying to write to the output streams closed by the parent process my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cout; close $cerr; # if child process tries to write at this moment, it # will be killed by SIGPIPE while (waitpid($pid, 0) != $pid) {} # and as a result, $? may become different ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file); Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock So how about this? we read all data from the child process my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (<$cout>) {} while (<$cerr>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock No. Will deadlock if the child process writes more bytes than the pipe buffer size to STDERR my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (<$cout>) {}  # may enter deadlock at this point while (<$cerr>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 - Pipe and Deadlock Tip: passing undef as CHLD_ERR will send all output to CHLD_OUT my $pid = open3(my $cin, my $cout,  undef , @cmd); while (<$cout>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 – Better to use temporary files Advice: don’t use pipes, use temporary files (unless you need to read the output of the child process while it is running) my $cout = File::Temp->new(); my $pid = do { local *COUT = $cout; open3(my $cin, ’>&COUT’, 0, @cmd); } or die $!; while (waitpid($pid, 0) != $pid) {} seek($cout, 0, SEEK_SET) or die $!; # seek to the start ... Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 vs. open |- Q. Why use IPC::Open3 instead of open ’-| cmd > tmpfile’? A. to skip the shell invocation for speed and security Oct 15 2011 Unix Programming with Perl 2
IPC::Open3 vs. open |- (2) Escaping for open |- is difficult # using IPC::Open3 my @cmd = ( $prog, ’-e’, $arg2, ); my $pid = open3(my $cin, my $cout, 0, @cmd) or die $!; # using open |- my $cmd = ”$prog –e $arg”; # need to escape $arg open my $fh, ’|-’,”$cmd > ” . $tempfh->filename  or die $!; Oct 15 2011 Unix Programming with Perl 2
Avoid shell invocation Shell invocation is evil ex. iT○ns upgrade accidentally removes user files failed to quote usernames with a whitespace Direct invocation is safer system($args) => system(@args) open | => IPC::Open2 or IPC::Open3 Oct 15 2011 Unix Programming with Perl 2
Rewriting open |- using IPC::Open3 # the original open(my $fh,’|-’, $cmd) or die $!; print $fh ”hello\n”; close $fh; # TODO: check $? # using IPC::Open3 my $pid = open3(my $fh,’>&STDOUT’, ’>&STDERR’, @cmd) or die $!; print $fh ”hello\n”; close $fh; while (waitpid($pid, 0) != $pid) {} # TODO: check $? Oct 15 2011 Unix Programming with Perl 2
Rewriting open -| using IPC::Open3 # the original open(my $fh,’-|’, $cmd) or die $!; my $line = <$fh>; close $fh; # TODO: check $? # using IPC::Open3 my $pid = open3(my $cin, my $fh, ’>&STDERR’, @cmd) or die $!; close $cin; my $line = <$fh>; close $fh; while (waitpid($pid, 0) != $pid) {} # TODO: check $? Oct 15 2011 Unix Programming with Perl 2
Signal and Race Condition Oct 15 2011 Unix Programming with Perl 2
How to sleep until receiving a signal? Is the code correct? my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; while (! $gothup) { sleep(30 * 60); # sleep for 30 minutes do_cleanup();  # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
How to sleep until receiving a signal? (2) a race condition exists my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; while (! $gothup) { # What happens if a signal is arrives here? # sleep() will sleep 30 minutes since it never # gets interrupted by the signal sleep(30 * 60); # sleep for 30 minutes do_cleanup();  # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
Use POSIX::pselect SIGHUP is blocked outside of pselect (and thus no race conditions) my $blocked = POSIX::SigSet->new(SIGHUP); my $unblocked = POSIX::SigSet->new(); my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; sigprocmask(SIG_BLOCK, $blocked, $unblocked); while (! $gothup) { pselect(undef, undef, undef, 30 * 60, $unblocked); do_cleanup();  # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
The problem of pselect Pselect has race condition on many environments, implemented like… sub select { my ($rset, $wset, $eset, $secs, $mask) = @_; my $oldmask = POSIX::SigSet->new(); sigprocmask(SIG_SETMASK, $mask, $oldmask); $oldmask); my $ret = select($rset, $wset, $eset, $secs); sigprocmask(SIG_SETMASK, $oldmask); $ret; } osx has the problem, glibc on linux does not have the problem but bionic (android) has the problem, … Oct 15 2011 Unix Programming with Perl 2
Using eval & die does not solve the problem my $blocked = POSIX::SigSet->new(SIGHUP); my $unblocked = POSIX::SigSet->new(); sigprocmask(SIG_BLOCK, $blocked, $unblocked); $SIG{HUP} = sub { die ’sighup:’ }; while (! $gothup) { { local $@; eval { sigprocmask(SIG_SETMASK, $unblocked); # what if the signal is delivered at the very moment the # perl interpreter calls sleep(3)? sleep(30 * 60); # sleep for 30 minutes }; $gothup = $@ =~ /^sighup:/; sigprocmask(SIG_SETMASK, $blocked); } do_cleanup();  # do some periodical tasks } Oct 15 2011 Unix Programming with Perl 2
The fix – call syswrite on signal # set unsafe signal handler (see perldoc perlipc) that converts a # signal to a message (Q. proper error handling as advised in this # year and last year’s slides are missing.  Can you name them?) socketpair(my $sig_rdr, my $sig_wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC)  or die $!; POSIX::sigaction(SIGHUP, POSIX::SigAction->new(sub { syswrite($sig_wtr, &quot;1&quot;, 1) == 1 or die $!; } })); while (1) { my $rfds = ''; vec($rfds, fileno($sig_rdr), 1) = 1; if (select($rfds, undef, undef, 30 * 60) > 0) { sysread($sig_rdr, my $buf, 1) == 1 or die $!; last; } do_cleanup();  # do some periodical tasks } Oct 15 2011 Unix Programming with Perl 2
Summary Oct 15 2011 Unix Programming with Perl 2
Summary buffer size is not infinite, be aware of deadlocks on inter-process / network communication avoid shell invocation, use system(@args) or IPC::Open3 be careful of race conditions when handling Unix signals Oct 15 2011 Unix Programming with Perl 2

More Related Content

PPT
Unix Programming with Perl
PPTX
Using the Power to Prove
PPT
Unix Shell Scripting Basics
PPT
Shell Scripting
PPT
Chap06
PPT
Unix And Shell Scripting
PDF
Put on Your Asynchronous Hat and Node
PDF
Shell scripting
Unix Programming with Perl
Using the Power to Prove
Unix Shell Scripting Basics
Shell Scripting
Chap06
Unix And Shell Scripting
Put on Your Asynchronous Hat and Node
Shell scripting

What's hot (20)

PDF
Quick start bash script
PPTX
Penetration testing using python
DOCX
Quize on scripting shell
PPTX
Cis 216 – shell scripting
PDF
various tricks for remote linux exploits  by Seok-Ha Lee (wh1ant)
ODP
Отладка в GDB
PDF
Shell Script
DOCX
32 shell-programming
PDF
Shell scripting
PPTX
Shell & Shell Script
ODP
Perl one-liners
PPTX
Shell Script Tutorial
ODP
Linux Command Line
PDF
Devinsampa nginx-scripting
PPTX
Process monitoring in UNIX shell scripting
PPT
Unix 5 en
PDF
PHP Internals and Virtual Machine
PPTX
Unix shell scripts
PPT
01 linux basics
PPTX
System Calls
Quick start bash script
Penetration testing using python
Quize on scripting shell
Cis 216 – shell scripting
various tricks for remote linux exploits  by Seok-Ha Lee (wh1ant)
Отладка в GDB
Shell Script
32 shell-programming
Shell scripting
Shell & Shell Script
Perl one-liners
Shell Script Tutorial
Linux Command Line
Devinsampa nginx-scripting
Process monitoring in UNIX shell scripting
Unix 5 en
PHP Internals and Virtual Machine
Unix shell scripts
01 linux basics
System Calls
Ad

Viewers also liked (20)

PPT
5 Accessing Information Resources
PPT
PHP - Introduction to PHP - Mazenet Solution
PPT
Final morris esri_nwgis_lidar
PPTX
eMail 101 (2) Class for Selfhelp Virtual Senior Center
PPT
Chapter 1Into the Internet
PPT
Chapter 4 Form Factors & Power Supplies
PDF
final emoji-board EMAIL ME NOWSWAG11
PPTX
Chapter 5 Input
KEY
Intermediate PHP
PPT
Chapter 10 Synchronous Communication
PDF
300 Years of Groundwater Management, Charles Porter
PPT
PHP 5.3 Part 1 - Introduction to PHP 5.3
PPT
Unix Master
PPT
Chapter 4 Form Factors Power Supplies
PDF
Appendex a
PDF
Drought: Looking Back and Planning Ahead, Todd Votteler
PDF
Appendex b
PDF
Guidelines for Modelling Groundwater Surface Water Interaction in eWater Source
PPT
Introduction to PHP
PPT
Chapter 10 Synchronous Communication
5 Accessing Information Resources
PHP - Introduction to PHP - Mazenet Solution
Final morris esri_nwgis_lidar
eMail 101 (2) Class for Selfhelp Virtual Senior Center
Chapter 1Into the Internet
Chapter 4 Form Factors & Power Supplies
final emoji-board EMAIL ME NOWSWAG11
Chapter 5 Input
Intermediate PHP
Chapter 10 Synchronous Communication
300 Years of Groundwater Management, Charles Porter
PHP 5.3 Part 1 - Introduction to PHP 5.3
Unix Master
Chapter 4 Form Factors Power Supplies
Appendex a
Drought: Looking Back and Planning Ahead, Todd Votteler
Appendex b
Guidelines for Modelling Groundwater Surface Water Interaction in eWater Source
Introduction to PHP
Chapter 10 Synchronous Communication
Ad

Similar to Unix Programming with Perl 2 (20)

PDF
Perl for System Automation - 01 Advanced File Processing
PDF
The Ruby Guide to *nix Plumbing: Hax0R R3dux
PPT
PHP CLI: A Cinderella Story
PPT
Perl Intro 8 File Handles
PDF
2008 07-24 kwpm-threads_and_synchronization
PDF
The Ruby Plumber's Guide to *nix
PDF
Processes in unix
PDF
IO Streams, Files and Directories
PDF
Perly Parallel Processing of Fixed Width Data Records
PPT
15237197jvkhcjkgckghckghxckgjckufliufi.ppt
PPTX
04_ForkPipe.pptx
PDF
An (abridged) Ruby Plumber's Guide to *nix
PDF
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
PDF
Perl_Part3
PDF
Perl Programming - 03 Programming File
PPT
PDF
System calls
Perl for System Automation - 01 Advanced File Processing
The Ruby Guide to *nix Plumbing: Hax0R R3dux
PHP CLI: A Cinderella Story
Perl Intro 8 File Handles
2008 07-24 kwpm-threads_and_synchronization
The Ruby Plumber's Guide to *nix
Processes in unix
IO Streams, Files and Directories
Perly Parallel Processing of Fixed Width Data Records
15237197jvkhcjkgckghckghxckgjckufliufi.ppt
04_ForkPipe.pptx
An (abridged) Ruby Plumber's Guide to *nix
WEB PROGRAMMING UNIT VI BY BHAVSINGH MALOTH
Perl_Part3
Perl Programming - 03 Programming File
System calls

More from Kazuho Oku (20)

PDF
HTTP/2で 速くなるとき ならないとき
PDF
QUIC標準化動向 〜2017/7
PDF
HTTP/2の課題と将来
PDF
TLS 1.3 と 0-RTT のこわ〜い話
PDF
Reorganizing Website Architecture for HTTP/2 and Beyond
PPTX
Recent Advances in HTTP, controlling them using ruby
PPTX
Programming TCP for responsiveness
PDF
Programming TCP for responsiveness
PDF
Developing the fastest HTTP/2 server
PPTX
TLS & LURK @ IETF 95
PPTX
HTTPとサーバ技術の最新動向
PPTX
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
PPTX
Cache aware-server-push in H2O version 1.5
PDF
HTTP/2時代のウェブサイト設計
PDF
H2O - making the Web faster
PDF
H2O - making HTTP better
PDF
H2O - the optimized HTTP server
PPTX
JSON SQL Injection and the Lessons Learned
PPTX
JSX 速さの秘密 - 高速なJavaScriptを書く方法
PPTX
JSX の現在と未来 - Oct 26 2013
HTTP/2で 速くなるとき ならないとき
QUIC標準化動向 〜2017/7
HTTP/2の課題と将来
TLS 1.3 と 0-RTT のこわ〜い話
Reorganizing Website Architecture for HTTP/2 and Beyond
Recent Advances in HTTP, controlling them using ruby
Programming TCP for responsiveness
Programming TCP for responsiveness
Developing the fastest HTTP/2 server
TLS & LURK @ IETF 95
HTTPとサーバ技術の最新動向
ウェブを速くするためにDeNAがやっていること - HTTP/2と、さらにその先
Cache aware-server-push in H2O version 1.5
HTTP/2時代のウェブサイト設計
H2O - making the Web faster
H2O - making HTTP better
H2O - the optimized HTTP server
JSON SQL Injection and the Lessons Learned
JSX 速さの秘密 - 高速なJavaScriptを書く方法
JSX の現在と未来 - Oct 26 2013

Recently uploaded (20)

PDF
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Big Data Technologies - Introduction.pptx
PPTX
MYSQL Presentation for SQL database connectivity
PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PPTX
A Presentation on Artificial Intelligence
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
NewMind AI Monthly Chronicles - July 2025
PDF
Machine learning based COVID-19 study performance prediction
PDF
Modernizing your data center with Dell and AMD
PDF
Network Security Unit 5.pdf for BCA BBA.
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Shreyas Phanse Resume: Experienced Backend Engineer | Java • Spring Boot • Ka...
Empathic Computing: Creating Shared Understanding
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
20250228 LYD VKU AI Blended-Learning.pptx
Advanced methodologies resolving dimensionality complications for autism neur...
Big Data Technologies - Introduction.pptx
MYSQL Presentation for SQL database connectivity
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
A Presentation on Artificial Intelligence
Per capita expenditure prediction using model stacking based on satellite ima...
Dropbox Q2 2025 Financial Results & Investor Presentation
NewMind AI Monthly Chronicles - July 2025
Machine learning based COVID-19 study performance prediction
Modernizing your data center with Dell and AMD
Network Security Unit 5.pdf for BCA BBA.
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Mobile App Security Testing_ A Comprehensive Guide.pdf
Understanding_Digital_Forensics_Presentation.pptx
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...

Unix Programming with Perl 2

  • 1. Unix Programming with Perl 2 DeNA Co., Ltd. Kazuho Oku
  • 2. Writing correct code tests aren’t enough tests don’t ensure that the code is correct writing correct code requires… knowledge of perl and knowledge of the OS Oct 15 2011 Unix Programming with Perl 2
  • 3. Last Year’s Talk Covered these aspects of Unix programming using Perl $! and Errno how to evaluate the errors file handles their internals interaction w. fork(2) Unix signals various signals and how to handle them writing cancellable code Oct 15 2011 Unix Programming with Perl 2
  • 4. Last Year’s Slides http://www.slideshare.net/kazuho/unix-programming-with-perl Oct 15 2011 Unix Programming with Perl 2
  • 5. Today’s Talk will cover more advanced topics inter-process communication Unix signals and race condition Oct 15 2011 Unix Programming with Perl 2
  • 6. IPC::Open3 Oct 15 2011 Unix Programming with Perl 2
  • 7. IPC::Open3 - Pipe and Deadlock # check syntax errors in perl scripts by using perl –c my @cmd = ( $^X, (map { &quot;-I$_&quot; } grep { !ref $_ } @INC), '-c', $file, ); my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file); http://d.hatena.ne.jp/tokuhirom/20100813/1281666615 Oct 15 2011 Unix Programming with Perl 2
  • 8. IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
  • 9. IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} A1. blocks if the child process reads from STDIN Oct 15 2011 Unix Programming with Perl 2
  • 10. IPC::Open3 - Pipe and Deadlock Close STDIN of the child before calling waitpid my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cin; while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
  • 11. IPC::Open3 - Pipe and Deadlock Q. generally speaking, this code might block. But when? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (waitpid($pid, 0) != $pid) {} A1. blocks if the child process reads from STDIN A2. blocks if the child process writes long data to STDOUT or STDERR Oct 15 2011 Unix Programming with Perl 2
  • 12. Size of the pipe buffer Pipe has size limit cannot write infinitely unless the other peer reads from pipe But actually, how large is the size limit? Oct 15 2011 Unix Programming with Perl 2
  • 13. Size of the pipe buffer (2) Checking the size of the pipe buffer for (my $sz = 1; ; $sz++) { my @cmd = ( $^X, '-e', qq(print &quot;1&quot;x$sz), ); my $pid = open3(my $cin, my $cout, 0, @cmd) or die $!; while (waitpid($pid, 0) != $pid) {} print &quot;size: $sz\n&quot;; } Oct 15 2011 Unix Programming with Perl 2
  • 14. Size of the pipe buffer (3) Size of the pipe buffer was… Linux 2.6.32 (x86-64): 65,536 bytes Mac OS X 10.6: 16,384 bytes Size may vary old versions of Linux: 4,096 bytes TCP streams and Unix sockets have configurable buffer size as well Oct 15 2011 Unix Programming with Perl 2
  • 15. IPC::Open3 - Pipe and Deadlock How should we avoid deadlocks? if we do not need the output of the child process (ex. perl –c), could this be the right answer? my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cout; close $cerr; while (waitpid($pid, 0) != $pid) {} ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file); Oct 15 2011 Unix Programming with Perl 2
  • 16. IPC::Open3 - Pipe and Deadlock No. The child process may get killed while trying to write to the output streams closed by the parent process my $pid = open3(my $cin, my $cout, my $cerr, @cmd); close $cout; close $cerr; # if child process tries to write at this moment, it # will be killed by SIGPIPE while (waitpid($pid, 0) != $pid) {} # and as a result, $? may become different ok((WIFEXITED($?) && WEXITSTATUS($?) == 0), $file); Oct 15 2011 Unix Programming with Perl 2
  • 17. IPC::Open3 - Pipe and Deadlock So how about this? we read all data from the child process my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (<$cout>) {} while (<$cerr>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
  • 18. IPC::Open3 - Pipe and Deadlock No. Will deadlock if the child process writes more bytes than the pipe buffer size to STDERR my $pid = open3(my $cin, my $cout, my $cerr, @cmd); while (<$cout>) {} # may enter deadlock at this point while (<$cerr>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
  • 19. IPC::Open3 - Pipe and Deadlock Tip: passing undef as CHLD_ERR will send all output to CHLD_OUT my $pid = open3(my $cin, my $cout, undef , @cmd); while (<$cout>) {} while (waitpid($pid, 0) != $pid) {} Oct 15 2011 Unix Programming with Perl 2
  • 20. IPC::Open3 – Better to use temporary files Advice: don’t use pipes, use temporary files (unless you need to read the output of the child process while it is running) my $cout = File::Temp->new(); my $pid = do { local *COUT = $cout; open3(my $cin, ’>&COUT’, 0, @cmd); } or die $!; while (waitpid($pid, 0) != $pid) {} seek($cout, 0, SEEK_SET) or die $!; # seek to the start ... Oct 15 2011 Unix Programming with Perl 2
  • 21. IPC::Open3 vs. open |- Q. Why use IPC::Open3 instead of open ’-| cmd > tmpfile’? A. to skip the shell invocation for speed and security Oct 15 2011 Unix Programming with Perl 2
  • 22. IPC::Open3 vs. open |- (2) Escaping for open |- is difficult # using IPC::Open3 my @cmd = ( $prog, ’-e’, $arg2, ); my $pid = open3(my $cin, my $cout, 0, @cmd) or die $!; # using open |- my $cmd = ”$prog –e $arg”; # need to escape $arg open my $fh, ’|-’,”$cmd > ” . $tempfh->filename or die $!; Oct 15 2011 Unix Programming with Perl 2
  • 23. Avoid shell invocation Shell invocation is evil ex. iT○ns upgrade accidentally removes user files failed to quote usernames with a whitespace Direct invocation is safer system($args) => system(@args) open | => IPC::Open2 or IPC::Open3 Oct 15 2011 Unix Programming with Perl 2
  • 24. Rewriting open |- using IPC::Open3 # the original open(my $fh,’|-’, $cmd) or die $!; print $fh ”hello\n”; close $fh; # TODO: check $? # using IPC::Open3 my $pid = open3(my $fh,’>&STDOUT’, ’>&STDERR’, @cmd) or die $!; print $fh ”hello\n”; close $fh; while (waitpid($pid, 0) != $pid) {} # TODO: check $? Oct 15 2011 Unix Programming with Perl 2
  • 25. Rewriting open -| using IPC::Open3 # the original open(my $fh,’-|’, $cmd) or die $!; my $line = <$fh>; close $fh; # TODO: check $? # using IPC::Open3 my $pid = open3(my $cin, my $fh, ’>&STDERR’, @cmd) or die $!; close $cin; my $line = <$fh>; close $fh; while (waitpid($pid, 0) != $pid) {} # TODO: check $? Oct 15 2011 Unix Programming with Perl 2
  • 26. Signal and Race Condition Oct 15 2011 Unix Programming with Perl 2
  • 27. How to sleep until receiving a signal? Is the code correct? my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; while (! $gothup) { sleep(30 * 60); # sleep for 30 minutes do_cleanup(); # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
  • 28. How to sleep until receiving a signal? (2) a race condition exists my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; while (! $gothup) { # What happens if a signal is arrives here? # sleep() will sleep 30 minutes since it never # gets interrupted by the signal sleep(30 * 60); # sleep for 30 minutes do_cleanup(); # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
  • 29. Use POSIX::pselect SIGHUP is blocked outside of pselect (and thus no race conditions) my $blocked = POSIX::SigSet->new(SIGHUP); my $unblocked = POSIX::SigSet->new(); my $gothup = 0; local $SIG{HUP} = sub { $gothup++ }; sigprocmask(SIG_BLOCK, $blocked, $unblocked); while (! $gothup) { pselect(undef, undef, undef, 30 * 60, $unblocked); do_cleanup(); # do some periodical tasks } print ”SIGHUP!\n”; Oct 15 2011 Unix Programming with Perl 2
  • 30. The problem of pselect Pselect has race condition on many environments, implemented like… sub select { my ($rset, $wset, $eset, $secs, $mask) = @_; my $oldmask = POSIX::SigSet->new(); sigprocmask(SIG_SETMASK, $mask, $oldmask); $oldmask); my $ret = select($rset, $wset, $eset, $secs); sigprocmask(SIG_SETMASK, $oldmask); $ret; } osx has the problem, glibc on linux does not have the problem but bionic (android) has the problem, … Oct 15 2011 Unix Programming with Perl 2
  • 31. Using eval & die does not solve the problem my $blocked = POSIX::SigSet->new(SIGHUP); my $unblocked = POSIX::SigSet->new(); sigprocmask(SIG_BLOCK, $blocked, $unblocked); $SIG{HUP} = sub { die ’sighup:’ }; while (! $gothup) { { local $@; eval { sigprocmask(SIG_SETMASK, $unblocked); # what if the signal is delivered at the very moment the # perl interpreter calls sleep(3)? sleep(30 * 60); # sleep for 30 minutes }; $gothup = $@ =~ /^sighup:/; sigprocmask(SIG_SETMASK, $blocked); } do_cleanup(); # do some periodical tasks } Oct 15 2011 Unix Programming with Perl 2
  • 32. The fix – call syswrite on signal # set unsafe signal handler (see perldoc perlipc) that converts a # signal to a message (Q. proper error handling as advised in this # year and last year’s slides are missing. Can you name them?) socketpair(my $sig_rdr, my $sig_wtr, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or die $!; POSIX::sigaction(SIGHUP, POSIX::SigAction->new(sub { syswrite($sig_wtr, &quot;1&quot;, 1) == 1 or die $!; } })); while (1) { my $rfds = ''; vec($rfds, fileno($sig_rdr), 1) = 1; if (select($rfds, undef, undef, 30 * 60) > 0) { sysread($sig_rdr, my $buf, 1) == 1 or die $!; last; } do_cleanup(); # do some periodical tasks } Oct 15 2011 Unix Programming with Perl 2
  • 33. Summary Oct 15 2011 Unix Programming with Perl 2
  • 34. Summary buffer size is not infinite, be aware of deadlocks on inter-process / network communication avoid shell invocation, use system(@args) or IPC::Open3 be careful of race conditions when handling Unix signals Oct 15 2011 Unix Programming with Perl 2