Convert Windows stubs to Unicode#58
Conversation
This updates our spawn vendored version to include janestreet/spawn#58. Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This updates our spawn vendored version to include janestreet/spawn#58. Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This updates our spawn vendored version to include janestreet/spawn#58. Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
src/dune
Outdated
| (run ocaml %{dep:flags.ml}))) | ||
|
|
||
| (rule | ||
| (with-stdout-to flags.ml |
There was a problem hiding this comment.
I think that this might add the Flags module to the library.
There was a problem hiding this comment.
Gah, yes indeed! Fix pushed for the original approach, but actually enabled_if is arguably "better", given that it's then a semi-pure Dune solution.
| /* Must come before any other caml/ headers are included */ | ||
| #define CAML_INTERNALS | ||
|
|
||
| #ifdef _WIN32 |
There was a problem hiding this comment.
Instead of changing the dune file:
| #ifdef _WIN32 | |
| #ifdef _WIN32 | |
| #define UNICODE | |
| #define _UNICODE | |
Based on a comment by @emillon in ocaml/dune#10212 (comment)
There was a problem hiding this comment.
My only concern is that UNICODE and _UNICODE must either be defined everywhere or nowhere (OCaml headers can pull in windows.h or parts of it as well, ending up with a similar problem to that which we have already had with CAML_INTERNALS).
The other benefit of putting it in flags is that any additional C files correctly inherit it, but that's really never likely to apply here. Given that we already have the _GNU_SOURCE definition (which is where it should go - i.e. right at the top).
I don't mind, though - how strong opinions against doing it "philosophically" correctly, if more complicatedly, in the dune file?
There was a problem hiding this comment.
I agree it is better to do it in the dune file.
|
@nojb could you have a look? |
nojb
left a comment
There was a problem hiding this comment.
LGTM (modulo the tweaks below)
src/spawn.ml
Outdated
| Buffer.contents buf | ||
| if env = [] then | ||
| "\000\000" | ||
| else |
There was a problem hiding this comment.
Can you say a word about this change?
There was a problem hiding this comment.
The environment block is supposed to be terminated with two NUL characters - if there are any bindings, that obviously in the other branch (and did in the ANSI version too). When there are no bindings, the ANSI version was passing a pointer to the OCaml string "\000" but that will have had an additional NUL terminator so it quietly worked. With the wide version, the issue was instantly revealed by one of the tests where CreateProcessW will have received two NUL bytes (i.e. a NUL wchar_t) but will have then "segfaulted" reading past the end of that buffer (CreateProcessW actually translated that to an invalid argument, which worryingly suggests that it carried on reading random memory and instead got upset that there was no = character anywhere or some such😱)
I'm not sure if it's worth a comment in the code - CreateProcess does indicate that the block should be a series of nul-terminated strings themselves terminated by another nul, it's just hazy on the case of an empty environment (not surprisingly, really).
There was a problem hiding this comment.
Thanks for the explanation; but then isn't it wrong in the compiler?
There was a problem hiding this comment.
Yeah, I had that same shock thought! 🙂 Just awaiting a train, and then I’ll flex some environments…
There was a problem hiding this comment.
OK, OCaml's fine because createprocess.c speculatively adds a nul character. I was speculatively adding that character but not zeroing it. I've fixed it by not adding it, as I think it's nicer that the function in spawn.ml is entirely responsible for producing the UTF-8 version and then the C stub transcodes exactly that string.
| /* Must come before any other caml/ headers are included */ | ||
| #define CAML_INTERNALS | ||
|
|
||
| #ifdef _WIN32 |
There was a problem hiding this comment.
I agree it is better to do it in the dune file.
src/spawn_stubs.c
Outdated
| win32_maperr(GetLastError()); | ||
| caml_win32_maperr(GetLastError()); | ||
| close_std_handles(&si); | ||
| uerror("DuplicateHandle", Nothing); |
There was a problem hiding this comment.
If we error out here, we will leak the strings allocated above. Maybe invert the order?
There was a problem hiding this comment.
Oh blimey, good catch. (Another) revised version incoming...
|
ok, thanks. my only concern with the dune file was that it requires changing a bit our bootstrap system in dune but that's fine with me. |
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
If the duplication of the handles failed, then the memory allocated for the strings wasn't freed. Duplicate the handles first - the only failure for the strings is OOM, and all bets are then off. Signed-off-by: David Allsopp <david.allsopp@metastack.com>
2ff553a to
5958e51
Compare
|
While looking at it again, for some reason the check for nul characters in environment values was only being done in Hopefully this is the last version 🙂 |
nojb
left a comment
There was a problem hiding this comment.
LGTM (after the latest changes). Thanks!
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes #10180 Signed-off-by: Etienne Millon <me@emillon.org>
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes ocaml#10180 Signed-off-by: Etienne Millon <me@emillon.org>
This does several things: - update our spawn vendored version to include janestreet/spawn#58 - pick the dune file - add new build flags for bootstrapping Fixes #10180 Signed-off-by: Etienne Millon <me@emillon.org> Co-authored-by: Etienne Millon <me@emillon.org>
CHANGES: - Support older GCC like 4.8.5 (janestreet/spawn#59) - Fix spawning processes on Windows when environment contains non-ascii characters (janestreet/spawn#58) - Skip calls to pthread_cancelstate on android, as its not available (janestreet/spawn#52) - Fix compatibility with systems that do not define `PIPE_BUF`. Use `_POSIX_PIPE_BUF` as a fallback. (janestreet/spawn#49) - [haiku] Fix compilation on Haiku OS. The header sys/syscalls.h isn't available, neither is pipe2() - Allow setting the sigprocmask for spawned processes (janestreet/spawn#32)
CHANGES: - Support older GCC like 4.8.5 (janestreet/spawn#59) - Fix spawning processes on Windows when environment contains non-ascii characters (janestreet/spawn#58) - Skip calls to pthread_cancelstate on android, as its not available (janestreet/spawn#52) - Fix compatibility with systems that do not define `PIPE_BUF`. Use `_POSIX_PIPE_BUF` as a fallback. (janestreet/spawn#49) - [haiku] Fix compilation on Haiku OS. The header sys/syscalls.h isn't available, neither is pipe2() - Allow setting the sigprocmask for spawned processes (janestreet/spawn#32)
Subsumes #55. Fixes #57. Fixes ocaml/dune#10180 which then fixes ocaml/opam#5861.
Windows OCaml uses UTF-8 internally for environment variables. The
spawn_windowsstub was using the ANSI version ofCreateProcess(CreateProcessA) which causes the environment to become corrupted if the environment contained any non-ASCII characters (i.e. any UTF-8 sequences).Support for Windows 98 ended in July 2006, so I think we can risk using the Unicode version of
CreateProcess😉 The code mirrors that forUnix.create_process.