nodegit / nodegit/nodegit

nodegit crash when trying to use Submodule.foreach

Open
#925 14 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug
Dominant language
JavaScript
Stars
5.8k
Forks
704
PR merge metrics
No merged PRs in 30d

Description

I was trying to use nodegit to do a recursive clone, but was getting crashes left and right and couldn't figure out what was going on. I've found a workaround, but wanted to report the crash here.

As far as I can tell, if I used Submodule.foreach to iterate over the submodules and then call submodule.update, nodegit crashes the node process, and I get an error message popup that looks like this:

Microsoft Visual C++ Runtime Library
Assertion failed!

Program: ...re\node_modules\nodegit\build\Release\nodegit.node
File: ..\..\vendor\libgit2\src\repository.c
Line: 2111

Expression: repo && id

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

( Here's a link to an image of the screenshot: https://dl.dropboxusercontent.com/u/108847970/nodegit-crash-screenshot.png )

These's are the versions I'm running:

  • Windows 10 (x64)
  • nodejs 4.2.3 (x64)
  • nodegit 0.11.5

Here's some sample code that reproduces the issue for me:

var path = require("path");

var mkdirp = require("mkdirp");
var rimraf = require("rimraf");
var git = require("nodegit");
var reposPath = path.join(__dirname, "cloned-repos");
var repoPath = path.join(reposPath, "electron");
var cloneUrl = "https://github.com/atom/electron";

rimraf(reposPath, function (err) {
    if (err) {
        throw err;
    }
    mkdirp(reposPath, function (err) {
        if (err) {
            throw err;
        }

        console.log("Cloning '" + cloneUrl + "'...");

        git.Clone.clone(cloneUrl, repoPath, new git.CloneOptions()).then(function () {
            console.log("Cloned successfully!");

            git.Repository.open(repoPath)
                .then(function(repo) {
                    var p = Promise.resolve();

                    git.Submodule.foreach(repo, function(submodule) {
                        var name = submodule.name();
                        console.log("Found submodule: " + name);

                        p = p.then(
                            function() {
                                return new Promise(function(resolve, reject) {
                                    submodule.init(1).then(
                                        function() {
                                            console.log("Init success on " + name);

                                            submodule.update(1, new git.SubmoduleUpdateOptions()).then(
                                                function () {
                                                    console.log("Update success on " + name);
                                                    resolve();
                                                },
                                                reject
                                            );
                                        }, reject
                                    );
                                });
                            }
                        )
                    }).then(
                        function() {
                            console.log("Foreach is done.");

                            p.then(
                                function() {
                                    console.log("Everything is done.");
                                },
                                function(error) {
                                    console.error(error);
                                }
                            )
                        }
                    );
                });
        }, function (error) {
            console.error(error);
        });
    });
});

The workaround I discovered was that if I switch to using Repository.getSubmoduleNames and Submodule.lookup instead of Submodule.foreach, everything seems to work just fine.

Here's the sample code for that:

var path = require("path");

var mkdirp = require("mkdirp");
var rimraf = require("rimraf");
var git = require("nodegit");
var reposPath = path.join(__dirname, "cloned-repos");
var repoPath = path.join(reposPath, "electron");
var cloneUrl = "https://github.com/atom/electron";

rimraf(reposPath, function (err) {
    if (err) {
        throw err;
    }
    mkdirp(reposPath, function (err) {
        if (err) {
            throw err;
        }

        console.log("Cloning '" + cloneUrl + "'...");

        git.Clone.clone(cloneUrl, repoPath, new git.CloneOptions()).then(function () {
            console.log("Cloned successfully!");

            git.Repository.open(repoPath)
                .then(function(repo) {

                    repo.getSubmoduleNames().then(
                        function(names) {
                            console.log("Found the following submodules:");
                            console.log(names);

                            var p = Promise.resolve();

                            names.forEach(function(name) {
                                p = p.then(
                                    function() {
                                        return new Promise(function(resolve, reject) {
                                            git.Submodule.lookup(repo, name).then(
                                                function (submodule) {
                                                    submodule.init(1).then(
                                                        function() {
                                                            console.log("Init success on " + name);

                                                            submodule.update(1, new git.SubmoduleUpdateOptions()).then(
                                                                function () {
                                                                    console.log("Update success on " + name);
                                                                    resolve();
                                                                },
                                                                reject
                                                            );
                                                        }, reject
                                                    );
                                                }, reject
                                            );
                                        });
                                    }
                                )
                            });

                            return p;
                        }
                    ).then(
                        function() {
                            console.log("Done!");
                        },
                        function(error) {
                            console.error(error);
                        }
                    );
                });
        }, function (error) {
            console.error(error);
        });
    });
});

A zip of the files used in the above examples (including my compiled version of nodegit) is available here if that helps at all: https://dl.dropboxusercontent.com/u/108847970/nodegit-foreach-failure.zip

I had screen other crashes in the past when I was using Submodule.foreach as well, but I had never been able to identify the cause as being that specific function. Now I think that it was.

I would try to track down this issue to the source myself, but I have no idea where to even start on debugging this kind of thing 😛

Let me know if I can provide any other additional information.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the crash with Submodule.foreach followed by submodule.init and submodule.update on the supplied Windows and nodegit versions, then compare that path with Repository.getSubmoduleNames and Submodule.lookup. Inspect the Submodule.foreach binding and vendor/libgit2/src/repository.c at line 2111; done means the reproduced operation no longer crashes the Node process.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, nodejs
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.