-
Notifications
You must be signed in to change notification settings - Fork 65
/
Copy path285-30771135.patch
103 lines (101 loc) · 2.98 KB
/
285-30771135.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
This patch is taken from the community. Details at
https://github.com/att/ast/pull/199
--- INIT.2012-08-01.old/src/cmd/ksh93/include/io.h 2018-03-02 02:24:24.912811320 -0800
+++ INIT.2012-08-01/src/cmd/ksh93/include/io.h 2018-03-02 02:28:36.169259620 -0800
@@ -81,6 +81,7 @@
extern Sfio_t *sh_iostream(Shell_t*,int);
extern int sh_redirect(Shell_t*,struct ionod*,int);
extern void sh_iosave(Shell_t *, int,int,char*);
+extern int sh_get_unused_fd(Shell_t* shp, int min_fd);
extern int sh_iovalidfd(Shell_t*, int);
extern int sh_inuse(Shell_t*, int);
extern void sh_iounsave(Shell_t*);
--- INIT.2012-08-01.old/src/cmd/ksh93/sh/io.c 2018-03-02 02:24:24.866327780 -0800
+++ INIT.2012-08-01/src/cmd/ksh93/sh/io.c 2018-03-02 02:28:07.282906200 -0800
@@ -2764,3 +2764,21 @@
return(r);
}
+// Return the lowest numbered fd that is equal to or greater than the requested
+// `min_fd` and which is not currently in use.
+int sh_get_unused_fd(Shell_t* shp, int min_fd) {
+ int fd;
+
+ while (1) {
+ if (fcntl(min_fd, F_GETFD) == -1) {
+ for(fd = 0; fd < shp->topfd; fd++) {
+ if (filemap[fd].save_fd == min_fd || filemap[fd].orig_fd == min_fd) break;
+ }
+ if (fd == shp->topfd) break;
+ }
+ min_fd++;
+ }
+
+ return min_fd;
+}
+
--- INIT.2012-08-01.old/src/cmd/ksh93/sh/subshell.c 2018-03-02 02:24:24.872777260 -0800
+++ INIT.2012-08-01.old/src/cmd/ksh93/sh/subshell.c 2018-03-02 02:29:44.023195350 -0800
@@ -678,7 +678,7 @@
}
if(iop && sffileno(iop)==1)
{
- int fd=sfsetfd(iop,3);
+ int fd=sfsetfd(iop,sh_get_unused_fd(shp, 3));
if(fd<0)
{
shp->toomany = 1;
--- INIT.2012-08-01.old/src/cmd/ksh93/tests/subshell.sh 2018-03-02 02:24:24.889843960 -0800
+++ INIT.2012-08-01/src/cmd/ksh93/tests/subshell.sh 2018-03-02 02:31:10.236185180 -0800
@@ -617,4 +617,53 @@
fi
done
+# ========================================
+# Test that closing file descriptors don't affect capturing the output of a
+# subshell. Regression test for issue #198.
+tmpfile=$(mktemp)
+expected='return value'
+
+function get_value {
+ case=$1
+ (( case >= 1 )) && exec 3< $tmpfile
+ (( case >= 2 )) && exec 4< $tmpfile
+ (( case >= 3 )) && exec 6< $tmpfile
+
+ # To trigger the bug we have to spawn an external command. Why is a
+ # mystery but not really relevant.
+ $(whence -p true)
+
+ (( case >= 1 )) && exec 3<&-
+ (( case >= 2 )) && exec 4<&-
+ (( case >= 3 )) && exec 6<&-
+
+ print $expected
+}
+
+actual=$(get_value 0)
+if [[ $actual != $expected ]]
+then
+ err_exit -u2 "failed to capture subshell output when closing fd: case 0"
+fi
+
+actual=$(get_value 1)
+if [[ $actual != $expected ]]
+then
+ err_exit -u2 "failed to capture subshell output when closing fd: case 1"
+fi
+
+actual=$(get_value 2)
+if [[ $actual != $expected ]]
+then
+ err_exit -u2 "failed to capture subshell output when closing fd: case 2"
+fi
+
+actual=$(get_value 3)
+if [[ $actual != $expected ]]
+then
+ err_exit -u2 "failed to capture subshell output when closing fd: case 3"
+fi
+
+rm $tmpfile
+
exit $((Errors<125?Errors:125))