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

Add C# (.NET Core) #64

Merged
merged 70 commits into from
Feb 9, 2020
Merged

Add C# (.NET Core) #64

merged 70 commits into from
Feb 9, 2020

Conversation

puqeko
Copy link
Member

@puqeko puqeko commented Jan 23, 2020

Possible replacement for #56. However, it has been much more involved than Mono to get going.

Tested the install script on my machine and had C# compiling and running on train but a few issues came up.

  • The csc.dll prints everything to stdout. This means that errors don't tell nztrain that compilation failed and instead qless crashes because there is no output file. Fixed by creating a shell script to redirect the version info to stdout and the errors to stderr. The shell script needed to return the exit status of the command.
  • The path to the buildtime reference assemblies has a more specific version number (3.1.101) than can be specified during install (3.1.1). Hence, it is possible this path will break if someone downloads a future 3.3.1. I couldn't figure out how to make the compiler command generic in bash. Fixed thanks to @Holmes98
  • I'm not sure if I have included enough compile time references. It's just the one file - I tried executing a file which utilised System.Collections and it still worked so I presume all the fundamental stuff is available.
  • The dotnet command needed to be given a .json file to tell which runtime framework version to use.

If someone could please check over that would be great.

This was referenced Jan 23, 2020
@tom93 tom93 self-requested a review January 23, 2020 16:58
@puqeko
Copy link
Member Author

puqeko commented Jan 23, 2020

Not a very descriptive commit message on my part (bac5179). I changed the shebang at some point and it turned out that isolate didn't like it so I've changed it back to \bin\bash\.

For some reason, the .sh file's output isn't being captured by isolate and I'm not sure why. The code in that area is a bit of a mess.

Consequences of not capturing output:

  • If the code compiles and runs successfully it will work fine.
  • If any errors occur then nztrain won't know and will continue until something breaks.
  • Version info isn't displayed.

 2020-01-24 at 11 48 45 AM

Copy link
Member

@Holmes98 Holmes98 left a comment

Choose a reason for hiding this comment

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

It gives me the following error when running inside chroot (/srv/chroot/nztrain) unless /proc is mounted, nevermind, it works now.

/usr/bin/csc: line 10: /dev/stdout: No such file or directory
Failed to resolve full path of the current executable [/proc/self/exe]
/usr/bin/csc: line 17: /dev/stderr: No such file or directory
Failed to resolve full path of the current executable [/proc/self/exe]

script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/csharp/dotnet-config-template.json Outdated Show resolved Hide resolved
db/languages.yml Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/csharp/compile-command.sh Outdated Show resolved Hide resolved
script/csharp/compile-command.sh Outdated Show resolved Hide resolved
@@ -58,7 +58,7 @@ def self.submission_options

# for the selection dropdown
def self.grouped_submission_options
current = ["c++", "c", "python", "java", "haskell", "ruby", "j"] # language group identifiers, order is preserved
current = ["c++", "csharp", "c", "python", "java", "haskell", "ruby", "j"] # language group identifiers, order is preserved
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
current = ["c++", "csharp", "c", "python", "java", "haskell", "ruby", "j"] # language group identifiers, order is preserved
current = ["c++", "c", "python", "csharp", "java", "haskell", "ruby", "j"] # language group identifiers, order is preserved

The "Current" languages are ordered by preference; I think C# should be further down (after Python).

Copy link
Member

Choose a reason for hiding this comment

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

In that case, should we also move Python above C?

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like C and C++ should be together...

Copy link
Member Author

Choose a reason for hiding this comment

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

We should probably decide what to order on. If it is by "preference" then Python is more popular for NZIC followed by C++. Hardly anyone uses C so, although I agree that they usually belong together, it would make more sense under this scheme to have C further down.

Copy link
Member Author

Choose a reason for hiding this comment

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

But it seems, at least, we all agree that Python should move ahead of C#. So that's something :)

Copy link
Contributor

Choose a reason for hiding this comment

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

How about we merge the last two?

Favourite/Pinned/Official
    C++
    Python
Other
    [list everything alphabetically]

Copy link
Contributor

Choose a reason for hiding this comment

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

(if we can't settle on good names, we can use a separator, "----")

Copy link
Member

Choose a reason for hiding this comment

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

I think we couldn't work out how to add a non-selectable separator (without optgroups) but otherwise I like the last option the most.

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed. The non-selectable separator was before I started using groups, so hopefully it shouldn't be difficult.

Copy link
Contributor

Choose a reason for hiding this comment

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

This makes a non-selectable separator: ["────────", "", {disabled: true}]
(credit for the unicode magic: https://stackoverflow.com/questions/899148/html-select-option-separator)

Copy link
Contributor

@tom93 tom93 left a comment

Choose a reason for hiding this comment

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

Round 1 of review comments, lots of comments but they are all minor things. I've pushed a draft with the suggested changes to branch add-csharp-core-suggestions-1.

script/csharp/compile-command.sh Outdated Show resolved Hide resolved
Comment on lines 10 to 11
/usr/bin/dotnet "/usr/share/dotnet/sdk/"$VERSION"/Roslyn/bincore/csc.dll" \
-reference:"/usr/share/dotnet/sdk/"$VERSION"/ref/netstandard.dll" "$@" 1>&2
Copy link
Contributor

Choose a reason for hiding this comment

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

  • No need for full path to dotnet
  • The full strings should be quoted; remove the quotes next to $VERSION
  • csc.dll prints version number of the C# compiler, I think the .NET Core SDK version should be added: echo ".NET Core SDK $VERSION" >&2
  • I would indent the continuation line 2 spaces

Copy link
Member Author

@puqeko puqeko Jan 30, 2020

Choose a reason for hiding this comment

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

No need for full path to dotnet

Why then have we been specifying /usr/bin/g++ etc for the rest of them? It would be more readable to keep it short. I tested this with g++ and it worked but python did not work without /usr/bin. Perhaps further investigation in another PR.

csc.dll prints version number of the C# compiler, I think the .NET Core SDK version should be added

Makes sense. Do we bother removing the copyright line in keeping with GHC and GCC?

Copy link
Contributor

@tom93 tom93 Jan 30, 2020

Choose a reason for hiding this comment

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

Why then have we been specifying /usr/bin/g++ etc for the rest of them? It would be more readable to keep it short. I tested this with g++ and it worked but python did not work without /usr/bin. Perhaps further investigation in another PR.

When a command (array of arguments) is executed using isolate, the first argument needs to be the full path to the program and the remaining arguments are passed as argv[1] etc. At first, the compilation commands were executed directly using isolate so the first argument needed to be the full path to the compiler (e.g. /usr/bin/g++).

When Java was added (32dcf29) it required two commands during compilation, javac and jar, so the compilation commands were wrapped in bash (e.g. first arg = /bin/bash, second arg = -c, third arg = javac ... && jar ...). Since the compilation command is now executed by bash, it can use shell operators like &&. It also doesn't need to use full paths to programs because bash searches for them in $PATH.

Python still requires a full path because it is an interpreter command, and they aren't wrapped in bash.

But all this is only for commands in db/languages.yml that are going to be executed directly by isolate, i.e. interpreter commands (and historically compilation commands). Inside a bash script like compile-command.sh there is no need to use full paths to programs because bash searches for them in $PATH.

csc.dll prints version number of the C# compiler, I think the .NET Core SDK version should be added

Makes sense. Do we bother removing the copyright line in keeping with GHC and GCC?

There is an option -nologo that removes the copyright message, so sure.

Copy link
Member Author

@puqeko puqeko Jan 30, 2020

Choose a reason for hiding this comment

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

Ah okay. Makes sense. In which case, I'd like to propose that we remove /usr/bin from all the current compile commands to make them more readable to users. Have opened #70

script/csharp/compile-command.sh Outdated Show resolved Hide resolved
db/languages.yml Outdated Show resolved Hide resolved
script/csharp/dotnet-config-template.json Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
Comment on lines 209 to 210
cp "script/csharp/compile-command.sh" "$ISOLATE_ROOT/usr/local/csc.sh"
chroot "$ISOLATE_ROOT" ln "/usr/local/csc.sh" "/usr/bin/csc"
Copy link
Contributor

@tom93 tom93 Jan 30, 2020

Choose a reason for hiding this comment

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

Any reason to both copy csc.sh and create a symlink? It would make sense if we were using update-alternatives to manage these links, but we're not. I would put it in /usr/local/bin, and copy it directly as /usr/local/bin/csc (the .sh suffix isn't significant).

Copy link
Member Author

@puqeko puqeko Jan 30, 2020

Choose a reason for hiding this comment

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

The intension was to be consistent with the other compile commands using /usr/bin/... since that part of the command displays on the submission page. Hence, I copied it into the sandbox and symlinked them in. Could we go with update-alternatives instead?

script/install/debootstrap.bash Outdated Show resolved Hide resolved
script/install/debootstrap.bash Outdated Show resolved Hide resolved
@puqeko
Copy link
Member Author

puqeko commented Jan 30, 2020

Other than the few things I've pointed out, your changes seem reasonable to me. Tested and works on my install

@tom93
Copy link
Contributor

tom93 commented Jan 31, 2020

I'd prefer to use squash-and-merge because the history is complicated and not interesting. So there will be one commit with a new commit message (we can add "Co-Authored-By:" lines if we want).
If the squash-and-merge is done through GitHub, it sets the commit author to the author of the PR and the committer to "GitHub <noreply@github.com>". (Not sure what you mean by commit signature.)

@puqeko
Copy link
Member Author

puqeko commented Jan 31, 2020

I made 6b95210 before I saw your message. Is that sort-of inline with what you were thinking? By signature I meant that it had my work email which wasn't ideal

@tom93
Copy link
Contributor

tom93 commented Jan 31, 2020

Yes, it's exactly what I meant.
(The squash introduced some changes, e.g. the execute permission on the scripts was lost -- probably a Windows thing -- but I'm planning to add more review comments, so we could re-squash later.)

@puqeko
Copy link
Member Author

puqeko commented Jan 31, 2020

Okay, sounds good. Yeah I'm on a windows machine at work currently. Filling in time while stuff installs

@puqeko
Copy link
Member Author

puqeko commented Jan 31, 2020

Should I force push?

@tom93
Copy link
Contributor

tom93 commented Jan 31, 2020

I'd like to keep the full history in the pull request, and only squash/force-push when merging (also there are undesirable differences in the squashed commit).

tom93 added a commit that referenced this pull request Feb 4, 2020
It will be required if we want to build V8 in chroot.

.NET Core (#64) also requires /proc to be mounted.
@tom93
Copy link
Contributor

tom93 commented Feb 5, 2020

As discussed in chat, running dotnet using isolate on Linux < 4.14 produces the following error:

Failed to create CoreCLR, HRESULT: 0x8007001F

Running strace dotnet shows that it tries to use mlock, which isolate prevents:

...
membarrier(MEMBARRIER_CMD_QUERY, 0)     = 0x1 (MEMBARRIER_CMD_SHARED)
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b82ffccf000
mlock(0x2b82ffccf000, 4096)             = -1 EPERM (Operation not permitted)
write(2, "Failed to create CoreCLR, HRESUL"..., 45Failed to create CoreCLR, HRESULT: 0x8007001F) = 45

It works on Linux >= 4.14 because then MEMBARRIER_CMD_PRIVATE_EXPEDITED is available, and dotnet uses that instead of mlock (see https://github.com/dotnet/runtime/issues/10568, https://github.com/dotnet/coreclr/pull/20949).

The server currently runs Linux 4.4.0, so we need to update the kernel before deploying this PR. I created issue #73 to track that.

The rest of the file doesn't use single/double quotes consistently
(C/C++ have double quotes for everything; the other languages have
double quotes for names and single quotes for commands).

The quoting rules are different[1] but for the strings we have they
don't make a difference, so let's make the new C# section internally
consistent by using the same quoting style for the compiler and
interpreter commands.

[1] https://yaml.org/spec/1.2/spec.html#id2786942
Double-quoted strings support backslash escape sequences.
Single-quoted strings don't have escape sequences, embedded single
quotes must be repeated.
It's out of date (the script does more than the two things now), and
at least for me the comment doesn't help much because the explanations
are apparent from the script.
Copy link
Contributor

@tom93 tom93 left a comment

Choose a reason for hiding this comment

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

Round 2 of review. Draft with the suggested changes in branch add-csharp-core-suggestions-2, please review and merge into 'add-csharp-core'.

  • Change quoting style in languages.yml
  • Disable dotnet telemetry
    I'm personally against telemetry, and it also raises potential issues (network access inside the sandbox, performance impact)
  • Remove comments in csc script (they are already out-of-date and I don't think they help much)
  • Warn if the kernel version is < 4.14
  • Move install commands to a separate file
  • Rename csharp directory to dotnet

script/install/csharp/dotnet-csc Outdated Show resolved Hide resolved
It's describing the purpose of the file, not the path of an actual
file.
@puqeko
Copy link
Member Author

puqeko commented Feb 9, 2020

I haven't tested them but those changes seem reasonable to me. Making the quoting consistent for other languages could become part of PR #70 since that's related to cleaning up langauges.yml. Telemetry isn't any help to us. Should we re-open this PR so that we can see it's still active under the PR tab? Someone beat me to it

tom93
tom93 previously approved these changes Feb 9, 2020
Copy link
Contributor

@tom93 tom93 left a comment

Choose a reason for hiding this comment

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

Other than the process limit (discussion in chat), looks good to me. I'd squash with the following commit message:

Add C# (.NET Core) (#64)

Co-Authored-By: Holmes98 <jkhoo98@gmail.com>
Co-authored-by: tom93 <tomlevy93@gmail.com>

@Holmes98 Holmes98 merged commit 6b5b6a3 into deployed Feb 9, 2020
@Holmes98
Copy link
Member

Holmes98 commented Feb 9, 2020

Deployed successfully.

@Holmes98 Holmes98 deleted the add-csharp-core branch February 9, 2020 16:06
@tom93 tom93 changed the title Add C# (.Net Core) Add C# (.NET Core) Feb 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants