Skip to content

distutils is not reproducible #78214

Description

@vstinner
BPO 34033
Nosy @vstinner, @benjaminp, @encukou, @methane, @yan12125, @bmwiedemann, @jefferyto
PRs
  • bpo-34033: distutils: byte_compile() sort files #8057
  • gh-78214: marshal: Stabilize FLAG_REF usage #8226
  • Dependencies:

    Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2018-07-03.15:46:25.794>
    labels = ['3.8', 'library']
    title = 'distutils is not reproducible'
    updated_at = <Date 2020-04-10.13:23:09.703>
    user = 'https://github.com/vstinner'

    bugs.python.org fields:

    activity = <Date 2020-04-10.13:23:09.703>
    actor = 'yan12125'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2018-07-03.15:46:25.794>
    creator = 'vstinner'
    dependencies = ['31377', '34093']
    files = []
    hgrepos = []
    issue_num = 34033
    keywords = ['patch']
    message_count = 9.0
    messages = ['320988', '320990', '320991', '321383', '321408', '321432', '321434', '337975', '359595']
    nosy_count = 9.0
    nosy_names = ['vstinner', 'benjamin.peterson', 'petr.viktorin', 'sascha_silbe', 'zbysz', 'methane', 'yan12125', 'bmwiedemann', 'jefferyto']
    pr_nums = ['8057', '8226']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue34033'
    versions = ['Python 3.8']

    Activity

    1. vstinner commented on Jul 3, 2018

      @vstinner
      MemberAuthor

      Follow up of bpo-29708: OpenSUSE uses a downstream patch for distutils to fix https://bugzilla.opensuse.org/show_bug.cgi?id=1049186: distutils-reproducible-compile.patch. I converted the patch as a PR: PR 8057.

      Naoki INADA wrote:
      """
      Currently, marshal uses refcnt to determine using w_ref or not. Some immutable objects (especially, long and str) can be cached and reused. It may affects refcnt when byte compiling.

      I think we should use more deterministic way instead of refcnt. Maybe, count all constants in the module before marshal, like we did in compiling function for co_consts and co_names.
      As a bonus, it may reduce resource usage too by merging constants over functions.
      (e.g. ('self',) co_varnames and (None,) co_consts)
      """
      #8057 (comment)

      Serhiy Storchaka added:
      """
      I think we need to understand the issue better before committing changes. When found the source of unstability of file names, we can find other similar sources and make them stable too. For example if the source is listdir() or glob(), we can consider sorting results of all listdir() or glob() in distutils and related methods.

      On other side, if the problem is with reference counters in marshal, we can change the marshal module instead.
      """
      #8057 (comment)

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      on Jul 3, 2018
    3. vstinner commented on Jul 3, 2018

      @vstinner
      MemberAuthor

      Copy of https://bugzilla.opensuse.org/show_bug.cgi?id=1049186 first message:
      """
      e.g. python-simplejson has one-bit diffs in .pyc files
      See
      http://rb.zq1.de/compare.factory-20170713/python-simplejson-compare.out

      in python3-simplejson.rpm we get
      -00004e50 68 6f 72 5f 5f da 07 64 65 63 69 6d 61 6c 72 0c |hor__..decimalr.|
      +00004e50 68 6f 72 5f 5f 5a 07 64 65 63 69 6d 61 6c 72 0c |hor__Z.decimalr.|

      in python3-simplejson-test.rpm we get the opposite change
      -00000580 72 13 00 00 00 5a 07 64 65 63 69 6d 61 6c 72 03 |r....Z.decimalr.|
      +00000580 72 13 00 00 00 da 07 64 65 63 69 6d 61 6c 72 03 |r......decimalr.|

      and it seems to be related to filesystem ordering, since it built reproducibly
      when using a filesystem with sorted readdir
      using disorderfs via reproducible-faketools-filesys from
      https://build.opensuse.org/package/show/home:bmwiedemann:reproducible/reproducible-faketools
      """
      https://bugzilla.opensuse.org/show_bug.cgi?id=1049186#c0

    4. benjaminp commented on Jul 3, 2018

      @benjaminp
      Contributor

      I agree that we should fix the underlying issue (marshal) rather than papering over it by sorting. In fact, we should have a test that compiles a bunch of pycs in a random orders and sees if they're the same or not.

    5. methane commented on Jul 10, 2018

      @methane
      Member

      Is this issue for only known marshal issue?
      Or is this issue for all issues in distutils including unknowns?

    6. benjaminp commented on Jul 11, 2018

      @benjaminp
      Contributor

      We should probably discuss the marshal issue in the preëxisting bpo-31377.

      I'm not sure if "distutils is not reproducible" is a larger issue than "pyc compilation is not reproducible". This issue could be a meta issue for either.

    7. vstinner commented on Jul 11, 2018

      @vstinner
      MemberAuthor

      Is this issue for only known marshal issue?

      IMHO the order in which .pyc files are created on disk also matters. It changes the result of "os.listdir()": some application can rely on unsorted os.listdir(). sorted() seems simple and hardless compared to the benefit.

    8. methane commented on Jul 11, 2018

      @methane
      Member

      OK, I created sub issue for pyc.

    9. bmwiedemann commented on Mar 15, 2019

      bmwiedemannmannequin
      Mannequin

      unreproducible .pyc files are still one of the major headaches for my work on openSUSE reproducible builds.

      There is also one aspect where i586 builds end up with different .pyc files than x86_64 builds. And then we randomly chose one of them for our "noarch" python module packages and hope they work everywhere (including on arm and s390 architectures).

      So is someone working towards a concept that makes it is possible to create the same .pyc files anywhere?
      Can I help something there?
      Is there an ETA?

    10. encukou commented on Jan 8, 2020

      @encukou
      Member

      There is also one aspect where i586 builds end up with different .pyc files than x86_64 builds. And then we randomly chose one of them for our "noarch" python module packages and hope they work everywhere (including on arm and s390 architectures).

      They are functionally identical, despite not being bit-by-bit identical.
      If they do not work everywhere, it's a very serious bug.

      So is someone working towards a concept that makes it is possible to create the same .pyc files anywhere?

      No, it's a known issue no one is working on.

      Can I help something there?

      Maybe?
      The two main culprits are in the marshal serialization algorithm: https://github.com/python/cpython/blob/master/Python/marshal.c
      Specifically:

      • a heuristic depends on refcount (i.e. state of objects in the entire interpreter, rather than just relationships between serialized objects):
        /* if it has only one reference, it definitely isn't shared */
      • (frozen)sets are serialized in iteration order, which is unpredictable (and determinig a predictable order is not trivial):
        else if (PyAnySet_CheckExact(v)) {

      A solution will probably come with an unacceptable performance hit -- it's good to keep generating the .pyc files fast. Two options to overcome that come to mind:

      • make reproducibility optional (which would make the testing more cumbersome)
      • make an add-on tool to re-serialize an existing .pyc.
    11. transferred this issue fromon Apr 10, 2022
    12. added a commit that references this issue on May 4, 2022
    13. added
      3.11only security fixes
      and removed on May 4, 2022
    14. vstinner commented on May 12, 2022

      @vstinner
      MemberAuthor

      @methane: Yeah! Thank you for the 6dcfd6c fix.

    15. josch commented on May 13, 2022

      @josch

      Thank you @methane -- we are now carrying your patch in python 3.10 in Debian: https://sources.debian.org/src/python3.10/3.10.4-4/debian/patches/gh-78214.diff/

    16. AA-Turner commented on Jun 7, 2022

      @AA-Turner
      Member

      @vstinner should this be closed now or will there be any other patches to Distutils before its removal?

      A

    17. added
      pendingThe issue will be closed if no feedback is provided
      on Jun 7, 2022
    18. vstinner commented on Jun 7, 2022

      @vstinner
      MemberAuthor

      I don't know the status of this issue, you should ask @methane who is more involved in this topic.

    19. AA-Turner commented on Jun 7, 2022

      @AA-Turner
      Member

      Ahh sorry, I will wait for @methane's opinion.

      A

    20. methane commented on Jun 8, 2022

      @methane
      Member

      We have enough opening issues relating to reproducible pyc. So I agree to close this one.

    21. removed
      pendingThe issue will be closed if no feedback is provided
      on Jun 9, 2022
    22. added a commit that references this issue on Nov 28, 2024
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.11only security fixesstdlibStandard Library Python modules in the Lib/ directory

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions