Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
GHC
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Alexander Kaznacheev
GHC
Commits
c2faf554
Commit
c2faf554
authored
14 years ago
by
Simon Marlow
Browse files
Options
Downloads
Patches
Plain Diff
use Win32 CreateProcess() rather than mingw spawnv() (
#4531
)
parent
3137d259
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
driver/utils/cwrapper.c
+94
-37
94 additions, 37 deletions
driver/utils/cwrapper.c
with
94 additions
and
37 deletions
driver/utils/cwrapper.c
+
94
−
37
View file @
c2faf554
...
...
@@ -6,12 +6,11 @@
so that it uses our in-tree mingw. Hence this wrapper. */
#include
"cwrapper.h"
#include
<errno.h>
#include
<process.h>
#include
<stdio.h>
#include
<stdlib.h>
#include
<stdarg.h>
#include
<string.h>
#include
<windows.h>
void
die
(
const
char
*
fmt
,
...)
{
va_list
argp
;
...
...
@@ -51,49 +50,107 @@ char *mkString(const char *fmt, ...) {
return
p
;
}
char
*
quote
(
char
*
str
)
{
char
*
quotedStr
;
char
*
p
;
char
*
flattenAndQuoteArgs
(
char
*
ptr
,
int
argc
,
char
*
argv
[])
{
int
i
;
char
*
src
;
quotedStr
=
malloc
(
2
*
strlen
(
str
)
+
2
+
1
);
if
(
quotedStr
==
NULL
)
{
die
(
"malloc failed: errno %d: %s
\n
"
,
errno
,
strerror
(
errno
));
}
p
=
quotedStr
;
*
p
++
=
'"'
;
while
(
*
str
)
{
if
(
*
str
==
'"'
)
{
*
p
++
=
'\\'
;
for
(
i
=
0
;
i
<
argc
;
i
++
)
{
*
ptr
++
=
'"'
;
src
=
argv
[
i
];
while
(
*
src
)
{
if
(
*
src
==
'"'
)
{
*
ptr
++
=
'\\'
;
}
*
ptr
++
=
*
src
++
;
}
*
p
++
=
*
str
++
;
*
ptr
++
=
'"'
;
*
ptr
++
=
' '
;
}
*
p
++
=
'"'
;
*
p
=
'\0'
;
return
quotedStr
;
return
ptr
;
}
__attribute__
((
noreturn
))
int
run
(
char
*
exePath
,
int
numArgs1
,
char
**
args1
,
int
numArgs2
,
char
**
args2
)
{
char
**
p
;
char
**
newArgv
;
int
i
,
ret
;
__attribute__
((
noreturn
))
int
run
(
char
*
exePath
,
int
numArgs1
,
char
**
args1
,
int
numArgs2
,
char
**
args2
)
{
int
i
,
cmdline_len
;
char
*
new_cmdline
,
*
ptr
;
newArgv
=
malloc
(
sizeof
(
char
*
)
*
(
1
+
numArgs1
+
numArgs2
+
1
));
if
(
newArgv
==
NULL
)
{
die
(
"malloc failed: errno %d: %s
\n
"
,
errno
,
strerror
(
errno
));
STARTUPINFO
si
;
PROCESS_INFORMATION
pi
;
ZeroMemory
(
&
pi
,
sizeof
(
PROCESS_INFORMATION
));
ZeroMemory
(
&
si
,
sizeof
(
STARTUPINFO
));
si
.
cb
=
sizeof
(
STARTUPINFO
);
/* Compute length of the flattened 'argv'. for each arg:
* + 1 for the space
* + chars * 2 (accounting for possible escaping)
* + 2 for quotes
*/
cmdline_len
=
1
+
strlen
(
exePath
)
*
2
+
2
;
for
(
i
=
0
;
i
<
numArgs1
;
i
++
)
{
cmdline_len
+=
1
+
strlen
(
args1
[
i
])
*
2
+
2
;
}
p
=
newArgv
;
*
p
++
=
quote
(
exePath
);
for
(
i
=
0
;
i
<
numArgs1
;
i
++
)
{
*
p
++
=
quote
(
args1
[
i
]);
for
(
i
=
0
;
i
<
numArgs2
;
i
++
)
{
cmdline_len
+=
1
+
strlen
(
args2
[
i
])
*
2
+
2
;
}
for
(
i
=
0
;
i
<
numArgs2
;
i
++
)
{
*
p
++
=
quote
(
args2
[
i
]);
new_cmdline
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
cmdline_len
+
1
));
if
(
!
new_cmdline
)
{
die
(
"failed to start up %s; insufficient memory"
,
exePath
);
}
ptr
=
flattenAndQuoteArgs
(
new_cmdline
,
1
,
&
exePath
);
ptr
=
flattenAndQuoteArgs
(
ptr
,
numArgs1
,
args1
);
ptr
=
flattenAndQuoteArgs
(
ptr
,
numArgs2
,
args2
);
*--
ptr
=
'\0'
;
// replace the final space with \0
/* Note: Used to use _spawnv(_P_WAIT, ...) here, but it suffered
from the parent intercepting console events such as Ctrl-C,
which it shouldn't. Installing an ignore-all console handler
didn't do the trick either.
Irrespective of this issue, using CreateProcess() is preferable,
as it makes this wrapper work on both mingw and cygwin.
*/
#if 0
fprintf(stderr, "Invoking %s\n", new_cmdline); fflush(stderr);
#endif
if
(
!
CreateProcess
(
exePath
,
new_cmdline
,
NULL
,
NULL
,
TRUE
,
0
,
/* dwCreationFlags */
NULL
,
/* lpEnvironment */
NULL
,
/* lpCurrentDirectory */
&
si
,
/* lpStartupInfo */
&
pi
)
)
{
die
(
"Unable to start %s (error code: %lu)
\n
"
,
exePath
,
GetLastError
());
}
/* Disable handling of console events in the parent by dropping its
* connection to the console. This has the (minor) downside of not being
* able to subsequently emit any error messages to the console.
*/
FreeConsole
();
switch
(
WaitForSingleObject
(
pi
.
hProcess
,
INFINITE
)
)
{
case
WAIT_OBJECT_0
:
{
DWORD
pExitCode
;
if
(
GetExitCodeProcess
(
pi
.
hProcess
,
&
pExitCode
)
==
0
)
{
exit
(
1
);
}
exit
(
pExitCode
);
}
*
p
=
NULL
;
ret
=
spawnv
(
_P_WAIT
,
exePath
,
(
const
char
*
const
*
)
newArgv
);
if
(
errno
)
{
die
(
"spawnv failed: errno %d: %s
\n
"
,
errno
,
strerror
(
errno
));
case
WAIT_ABANDONED
:
case
WAIT_FAILED
:
/* in the event we get any hard errors, bring the child to a halt. */
TerminateProcess
(
pi
.
hProcess
,
1
);
exit
(
1
);
default:
exit
(
1
);
}
exit
(
ret
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment