Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unix.environment on Windows: use _wenviron #1369

Merged
merged 3 commits into from
Oct 10, 2017

Conversation

nojb
Copy link
Contributor

@nojb nojb commented Sep 25, 2017

One more rebase fix following #1200.

The existing Unix.environment in trunk uses the native Win32 API GetEnvironmentStrings which works OK except that its result can sometimes get out of sync with the result of the "POSIX" API _wgetenv used for Unix.{get,put}env (see MPR#4499 for details).

The mixup ocurred because at some point we had switched to using the native Win32 API in all three functions but later decided to leave that change for later.

This patch reverts Unix.environment to read from the global variable _wenviron, similar to the analogous implementation for Unix.

@@ -21,23 +21,26 @@
#include <caml/osdeps.h>

#include <Windows.h>
#include <Stdlib.h>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stdlib (lowercase) is more standard (also for windows.h, btw) in our codebase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, an quick check in the museum shows that Microsoft use Windows.h and stdlib.h (or, of course, STDLIB.H if you're very, very old...)

However, the MinGW headers use windows.h so it's anyone's guess really... let's hope no one is crazy enough to try running the kernel in case sensitive mode 😄

v = caml_copy_string_of_utf16(p);
Store_field(result, i ++, v);
if (_wenviron != NULL) {
nbr = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot one use caml_alloc_array as caml_copy_string_array does (passing caml_copy_string_of_utf16 instead)?

@alainfrisch
Copy link
Contributor

Could you create a test that would fail before this PR is merged?

@nojb
Copy link
Contributor Author

nojb commented Sep 26, 2017

The point of the PR is that it should be possible - except that today I can't seem to reproduce the failure locally, mmmph... Will investigate more, see if I can figure out what is going on.

In any case, it seems weird to use the native Win32 API for just one of the calls instead of all three.

@alainfrisch
Copy link
Contributor

At least for the ANSI version, my understanding of MPR4499 is that putenv indeed sends the new value to the "real "environment" (the one manipulated through GetEnvironmentVariable and co). If this is also the case for the W version of putenv, everything would be ok (although I understand it is not very nice to mix the two kinds of functions). It would actually be a bit "better" since this would allow to see changes performed through SetEnvironmentVariable (e.g. from .NET). But yes, it would actually be confusing to see changes that are invisible to getenv...

@dra27
Copy link
Member

dra27 commented Sep 27, 2017

Ugh, it's one of many ugly sections of the Microsoft C runtime! It feels somewhat icky because _environ and _wenviron are deprecated (however, MSVC also provides no enumeration functions, as far as I'm aware, so go figure!).

OCaml is supposed to sit atop a C runtime, even if it's an often irritating one, so I agree that correcting this one function is the way to go.

@damiendoligez damiendoligez added this to the 4.06.0 milestone Sep 27, 2017
@gasche gasche closed this Sep 27, 2017
@gasche gasche reopened this Sep 27, 2017
@nojb
Copy link
Contributor Author

nojb commented Sep 27, 2017

Do I need to add an entry to Changes?

@alainfrisch
Copy link
Contributor

Do I need to add an entry to Changes?

Perhaps mention it together with the entry for #1200.

@nojb
Copy link
Contributor Author

nojb commented Sep 27, 2017

Ah yes, of course!

wchar_t * envp, * p;
int size, i;
CAMLparam0 ();
CAMLlocal2 (v, result);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi!

Are the spaces after the function names introduced by design?

It's on line 28, 29, 36.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comment; and not, not really. Will fix it and give AppVeyor an excuse to wake up again.

@nojb nojb force-pushed the fix_unix_wenvironment branch 2 times, most recently from 674328c to 7822d54 Compare September 29, 2017 14:20
@nojb nojb force-pushed the fix_unix_wenvironment branch 2 times, most recently from 6b4326f to 652c6f5 Compare September 30, 2017 06:44
@dra27 dra27 closed this Sep 30, 2017
@dra27 dra27 reopened this Sep 30, 2017
@dra27 dra27 closed this Oct 1, 2017
@dra27 dra27 reopened this Oct 1, 2017
@xavierleroy
Copy link
Contributor

@alainfrisch suggested a possibly simpler implementation. Please tell why it would not work.

@nojb
Copy link
Contributor Author

nojb commented Oct 4, 2017

Yes, sorry about that, I forgot to post an answer here. The reason was that caml_copy_array is not "polymorphic" enough, it has signature

value caml_alloc_array(value (*funct)(char const *), char const ** arr)

(we need a version with wchar_t in lieu of char). It is tempting to change char * to void * in this signature, but then the funct argument will have type value (*funct)(void const *) and will not accept something less general like value caml_copy_string(char const *).

Anyone see a way around this?

@nojb
Copy link
Contributor Author

nojb commented Oct 4, 2017

Of course I can just cast the argument to use it (in fact I already used this once: https://github.com/ocaml/ocaml/blob/trunk/byterun/sys.c#L362). Shall I do that?

@nojb
Copy link
Contributor Author

nojb commented Oct 5, 2017

OK, absent any explicit decision I went ahead and added a commit using caml_alloc_array (with a cast), which looks simpler.

@gasche
Copy link
Member

gasche commented Oct 5, 2017

Is it possible/practical to add a regression test for the bug you are fixing?

@nojb
Copy link
Contributor Author

nojb commented Oct 5, 2017

Yes, it is! I added a test (test_env.ml) which fails on trunk and passes on this branch. I also added a second (disabled) test test_env2.ml which fails due to the closely related MPR#4499. I am preparing a PR for after 4.06 to fix the second one.

@gasche
Copy link
Member

gasche commented Oct 5, 2017

Is someone willing to review and approve the PR? ( @alainfrisch, @dra27 ? )

@nojb nojb force-pushed the fix_unix_wenvironment branch 2 times, most recently from feda74a to 37ae174 Compare October 10, 2017 10:42
let foo = "FOO"

let () =
set_environment_variable foo "BAR";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to have this test (disabled), but perhaps indicates somehow that it is related to MPR#4499, not the current PR.

Also, it might be good to use non-ASCII characters in the string.

@alainfrisch
Copy link
Contributor

LGTM (modulo a minor comment about the disabled test). Waiting for the CI green lights.

@nojb
Copy link
Contributor Author

nojb commented Oct 10, 2017

Rebased and amended as suggested:

  • Added a test to check non-ASCII characters being returned by Unix.environment to win-unicode/mltest.ml (Unix.{getenv,putenv} were already being tested)
  • Added a new test lib-unix/win-env/test_env.ml for this PR (fails on trunk)
  • Added a new test lib-unix/win-env/test_env2.ml, currently disabled (with a comment explaining why), that tests MPR#4499 which is closely related to the present PR.

- Add lib-unix/win-env/test_env.ml, a test that fails in trunk and passes in
  this PR.

- Add lib-unix/win-env/test_env2.ml: a test for MPR#4499 which is closely
  related to this PR.  Currently disabled as it fails.

- Added a new test in win-unicode/mltest.ml to test non-ASCII characters
  returned by Unix.environment (Unix.{getenv,putenv} were already being tested).
@gasche
Copy link
Member

gasche commented Oct 10, 2017

( @alainfrisch does your comment count as approval? Let's follow the process as it was suggested. )

@alainfrisch alainfrisch merged commit f32374d into ocaml:trunk Oct 10, 2017
@alainfrisch
Copy link
Contributor

@damiendoligez @gasche I'd like to cherry-pick this to 4.06. Do you agree?

@gasche
Copy link
Member

gasche commented Oct 10, 2017

Yes, I think it's good to have it in the first release with #1200. I would encourage you to include it in 4.06.

alainfrisch pushed a commit that referenced this pull request Oct 10, 2017
* Unix.environment on Windows: use _wenviron

* Add Changes entry

* Update testsuite

- Add lib-unix/win-env/test_env.ml, a test that fails in trunk and passes in
  this PR.

- Add lib-unix/win-env/test_env2.ml: a test for MPR#4499 which is closely
  related to this PR.  Currently disabled as it fails.

- Added a new test in win-unicode/mltest.ml to test non-ASCII characters
  returned by Unix.environment (Unix.{getenv,putenv} were already being tested).
@alainfrisch
Copy link
Contributor

Cherry-picked to 4.06 as 990845b.

EmileTrotignon pushed a commit to EmileTrotignon/ocaml that referenced this pull request Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants