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

MJIT MSVC: Use /Z7 to avoid PDB write race #5058

Merged
merged 2 commits into from Nov 24, 2021
Merged

Conversation

XrXr
Copy link
Member

@XrXr XrXr commented Oct 29, 2021

With MSVC, MJIT uses the /Fd option on an installed PDB file when
compiling. Combined with the /Zi option, this causes the PDB file to be
modified every time MJIT compiles. Concurrent modifications to the same
PDB file is known to cause problems. MSVC even has an option, /FS to
deal with it. When running MJIT tests in parallel, sometimes this leads
to corrupting the PDB file, breaking subsequent compilations. On CI,
we get messages like these:

rb_mjit_header-3.1.0.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.

To avoid this race, use the /Z7 option when building precompiled header,
which asks the compiler to put debug info into the .obj file,
eliminating the need for pointing the compiler to the PDB file for the
precompiled header.

The /Fd option is changed to use a unique path based on the name of the
dll output. Because of the /debug linker flag, we generate a PDB file
at runtime even though we use /Z7.

There are a couple things missing from this change:

  • Because MJIT uses the interpreter's CFLAGS build option and that
    contains /Zi, putting /Z7 at the end leads to a build warning
  • With /Z7 no PDB file is built anymore, so the code for installing
    the PDB file can be removed
    addressed in 28b528f

There might also be other problems with this change I haven't noticed
while developing this change using Github Actions. I don't have a
Windows dev environment with Visual Studio so I can't finish this
change easily. Please feel free to complete this change if it makes
sense.

Note:

  • On master, you can see the PDB file changing with llvm-pdbutil or a
    simple checksum. There is an age field in the file that is bumped
  • I'm not sure if users can specify compile flags on MSVC. If they
    couldn't, maybe it's easier to change MJIT's compile options to
    use /Z7 when building the precompile header.
  • MJIT could pass different options at runtime to generate fewer
    files. Right now it inherits the /DEBUG linker flag which causes
    a PDB file to be generated at runtime even though /Z7 is used.

Relevant MSVC docs:

@k0kubun

With MSVC, MJIT uses the /Fd option on an installed PDB file when
compiling. Combined with the /Zi option, this causes the PDB file to be
modified every time MJIT compiles. Concurrent modifications to the same
PDB file is known to cause problems. MSVC even has an option, /FS to
deal with it. When running MJIT tests in parallel, sometimes this leads
to corrupting the PDB file, breaking subsequent compilations. On CI,
we get messages like these:

    rb_mjit_header-3.1.0.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.

To avoid this race, use the /Z7 option when building precompiled header,
which asks the compiler to put debug info into the .obj file,
eliminating the need for pointing the compiler to the PDB file for the
precompiled header.

The /Fd option is changed to use a unique path based on the name of the
dll output. Because of the /debug linker flag, we generate a PDB file
at runtime even though we use /Z7.

There are a couple things missing from this change:
 - Because MJIT uses the interpreter's CFLAGS build option and that
   contains /Zi, putting /Z7 at the end leads to a build warning
 - With /Z7 no PDB file is built anymore, so the code for installing
   the PDB file can be removed

There might also be other problems with this change I haven't noticed
while developing this change using Github Actions. I don't have a
Windows dev environment with Visual Studio so I can't finish this
change easily. Please feel free to complete this change if it makes
sense.

Note:
 - On master, you can see the PDB file changing with llvm-pdbutil or a
   simple checksum. There is an age field in the file that is bumped
 - I'm not sure if users can specify compile flags on MSVC. If they
   couldn't, maybe it's easier to change MJIT's compile options to
   use /Z7 when building the precompile header.
 - MJIT could pass different options at runtime to generate fewer
   files. Right now it inherits the /DEBUG linker flag which causes
   a PDB file to be generated at runtime even though /Z7 is used.

Relevant MSVC docs:
 - [/Zi,/Z7](https://docs.microsoft.com/en-us/cpp/build/reference/z7-zi-zi-debug-information-format?view=msvc-160)
 - [/DEBUG](https://docs.microsoft.com/en-us/cpp/build/reference/debug-generate-debug-info?view=msvc-160)
 - [/FS](https://docs.microsoft.com/en-us/cpp/build/reference/fs-force-synchronous-pdb-writes?view=msvc-160)
Copy link
Member

@k0kubun k0kubun left a comment

Choose a reason for hiding this comment

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

Thank you so much for taking a look at this issue!

With /Z7, no .pdb file is generated, so trying to link it during build
fails on my machine even though it's okay on CI.

By the way, in my local testing, no .pdb is generated in cwd at runtime
even without the /Fd option. I guess we can pass it just in case.
@nobu nobu requested a review from unak November 1, 2021 04:00
Copy link
Member

@unak unak left a comment

Choose a reason for hiding this comment

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

ok, let's try

@unak unak marked this pull request as ready for review November 24, 2021 14:45
@unak unak merged commit 3d19c29 into ruby:master Nov 24, 2021
@XrXr XrXr deleted the mjit-msvc-z7 branch November 24, 2021 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants