6
6
// Defines _dup2() and _dup2_nolock, which duplicate lowio file handles
7
7
//
8
8
#include < corecrt_internal_lowio.h>
9
+ #include < corecrt_internal_ptd_propagation.h>
9
10
10
-
11
-
12
- static int __cdecl dup2_nolock (int const source_fh, int const target_fh) throw()
11
+ static int __cdecl _dup2_nolock_internal (int const source_fh, int const target_fh, __crt_cached_ptd_host& ptd) throw()
13
12
{
14
13
if ((_osfile (source_fh) & FOPEN) == 0 )
15
14
{
16
15
// If the source handle is not open, return an error. Noe that the
17
16
// DuplicateHandle API will not detect this error, because it implies
18
- // that _osfhnd(source_fh) == INVALID_HANDLE_VALUE, and this is a
17
+ // that _osfhnd(source_fh) == INVALID_HANDLE_VALUE, and this is a
19
18
// legal HANDLE value to be duplicated.
20
- errno = EBADF;
21
- _doserrno = 0 ;
19
+ ptd. get_errno (). set ( EBADF) ;
20
+ ptd. get_doserrno (). set ( 0 ) ;
22
21
_ASSERTE ((" Invalid file descriptor. File possibly closed by a different thread" ,0 ));
23
22
return -1 ;
24
23
}
25
24
26
- // If the target is open, close it first. We ignore the possibility of an
27
- // error here: an error simply means that the OS handle value may remain
28
- // bound for the duration of the process.
29
- if (_osfile (target_fh) & FOPEN)
30
- {
31
- _close_nolock (target_fh);
32
- }
33
-
34
25
// Duplicate the source file onto the target file:
35
26
intptr_t new_osfhandle;
36
27
@@ -45,10 +36,18 @@ static int __cdecl dup2_nolock(int const source_fh, int const target_fh) throw()
45
36
46
37
if (!result)
47
38
{
48
- __acrt_errno_map_os_error (GetLastError ());
39
+ __acrt_errno_map_os_error_ptd (GetLastError (), ptd );
49
40
return -1 ;
50
41
}
51
42
43
+ // If the target is open, close it once we know the OS handle was duplicated successfully.
44
+ // We ignore the possibility of an error here: an error simply means that the OS handle
45
+ // value may remain bound for the duration of the process.
46
+ if (_osfile (target_fh) & FOPEN)
47
+ {
48
+ _close_nolock_internal (target_fh, ptd);
49
+ }
50
+
52
51
__acrt_lowio_set_os_handle (target_fh, new_osfhandle);
53
52
54
53
// Copy the _osfile information, with the FNOINHERIT bit cleared:
@@ -59,30 +58,27 @@ static int __cdecl dup2_nolock(int const source_fh, int const target_fh) throw()
59
58
return 0 ;
60
59
}
61
60
62
-
63
-
64
- // _dup2() makes the target file handle a duplicate of the source file handle,
65
- // so that both handles refer to the same file. If the target handle is open
66
- // upon entry, it is closed so that it is not leaked.
67
- //
68
- // Returns 0 if successful; returns -1 and sets errno on failure.
69
- extern " C" int __cdecl _dup2 (int const source_fh, int const target_fh)
61
+ static int __cdecl _dup2_internal (int const source_fh, int const target_fh, __crt_cached_ptd_host& ptd) throw()
70
62
{
71
- _CHECK_FH_CLEAR_OSSERR_RETURN ( source_fh, EBADF, -1 );
72
- _VALIDATE_CLEAR_OSSERR_RETURN ( (source_fh >= 0 && (unsigned )source_fh < (unsigned )_nhandle), EBADF, -1 );
73
- _VALIDATE_CLEAR_OSSERR_RETURN ( (_osfile (source_fh) & FOPEN), EBADF, -1 );
74
- _CHECK_FH_CLEAR_OSSERR_RETURN ( target_fh, EBADF, -1 );
75
- _VALIDATE_CLEAR_OSSERR_RETURN ( ((unsigned )target_fh < _NHANDLE_), EBADF, -1 );
63
+ _UCRT_CHECK_FH_CLEAR_OSSERR_RETURN (ptd, source_fh, EBADF, -1 );
64
+ _UCRT_VALIDATE_CLEAR_OSSERR_RETURN (ptd, (source_fh >= 0 && (unsigned )source_fh < (unsigned )_nhandle), EBADF, -1 );
65
+ _UCRT_VALIDATE_CLEAR_OSSERR_RETURN (ptd, (_osfile (source_fh) & FOPEN), EBADF, -1 );
66
+ _UCRT_CHECK_FH_CLEAR_OSSERR_RETURN (ptd, target_fh, EBADF, -1 );
67
+ _UCRT_VALIDATE_CLEAR_OSSERR_RETURN (ptd, ((unsigned )target_fh < _NHANDLE_), EBADF, -1 );
76
68
77
69
// Make sure there is an __crt_lowio_handle_data struct corresponding to the target_fh:
78
70
if (target_fh >= _nhandle && __acrt_lowio_ensure_fh_exists (target_fh) != 0 )
71
+ {
79
72
return -1 ;
73
+ }
80
74
81
75
// If the source and target are the same, return success (we've already
82
76
// verified that the file handle is open, above). This is for conformance
83
77
// with the POSIX specification for dup2.
84
78
if (source_fh == target_fh)
79
+ {
85
80
return 0 ;
81
+ }
86
82
87
83
// Obtain the two file handle locks. In order to prevent deadlock, we
88
84
// always obtain the lock for the lower-numbered file handle first:
@@ -101,7 +97,7 @@ extern "C" int __cdecl _dup2(int const source_fh, int const target_fh)
101
97
102
98
__try
103
99
{
104
- result = dup2_nolock (source_fh, target_fh);
100
+ result = _dup2_nolock_internal (source_fh, target_fh, ptd );
105
101
}
106
102
__finally
107
103
{
@@ -111,3 +107,14 @@ extern "C" int __cdecl _dup2(int const source_fh, int const target_fh)
111
107
}
112
108
return result;
113
109
}
110
+
111
+ // _dup2() makes the target file handle a duplicate of the source file handle,
112
+ // so that both handles refer to the same file. If the target handle is open
113
+ // upon entry, it is closed so that it is not leaked.
114
+ //
115
+ // Returns 0 if successful; returns -1 and sets errno on failure.
116
+ extern " C" int __cdecl _dup2 (int const source_fh, int const target_fh)
117
+ {
118
+ __crt_cached_ptd_host ptd;
119
+ return _dup2_internal (source_fh, target_fh, ptd);
120
+ }
0 commit comments