-
Notifications
You must be signed in to change notification settings - Fork 448
Fix garbled characters in history view with non-ascii characters (fixes#124) #136
Conversation
Since the ReadLine() loop blocks I/O, use Stream::BeginRead instead.
|
@StanleyGoldman |
|
@StanleyGoldman
|
|
Hey @shiena, sorry it's taken so long to get to this. Processes are executed in a separate thread, so because of the bug in Unity we can definitely go with synchronous calls here. Also until Unity removes support for their .net 3.5 profile we will not compile this library in .net 4.6. So when you get the chance remove all the |
StanleyGoldman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove all the #if/#endif with NET_4_6
|
@StanleyGoldman Thank you for review. |
|
💨... Thanks for the quick changes ... |
| { | ||
| var encoded = outputEncoding.GetString(outputBuffer, 0, bytesRead); | ||
| outputContents.Append(encoded); | ||
| Process.StandardOutput.BaseStream.BeginRead(outputBuffer, 0, outputBuffer.Length, outputCallback, Process.StandardOutput); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this line of code should not be here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems I am mistaken
| { | ||
| var encoded = errorEncoding.GetString(errorBuffer, 0, bytesRead); | ||
| errorContents.Append(encoded); | ||
| Process.StandardError.BaseStream.BeginRead(errorBuffer, 0, errorBuffer.Length, errorCallback, Process.StandardError); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the same goes for this line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mistaken here too
|
I understand why you've done what you've done... 🤔... I'm thinking about it |
StanleyGoldman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand what happened now, you worked real hard to keep both async and sync methods possible. Since we are going to go sync, you can rewrite the way the output is being handled to be simpler & easier to follow.
| Process.BeginOutputReadLine(); | ||
| { | ||
| outputReset.Reset(); | ||
| Process.StandardOutput.BaseStream.BeginRead( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a loop here to read the bytes and encode the string with the correct encoding. After that you can read the lines and call the appropriate output method. This way we won't need the complicated AsyncCallback that has a reference to itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you read the standard output using a loop there, it blocks processing.
Because RunCredentialHelper writes to the standard input of git-credential-wincred command when signing in to GitHub.
Unity/src/GitHub.Api/Git/GitCredentialManager.cs
Lines 147 to 172 in 1476044
| Logger.Trace("RunCredentialHelper helper:\"{0}\" action:\"{1}\"", credHelper, action); | |
| SimpleProcessTask task; | |
| if (credHelper.StartsWith('!')) | |
| { | |
| // it's a separate app, run it as such | |
| task = new SimpleProcessTask(taskManager.Token, credHelper.Substring(1).ToNPath(), action); | |
| } | |
| else | |
| { | |
| var args = $"credential-{credHelper} {action}"; | |
| task = new SimpleProcessTask(taskManager.Token, args); | |
| } | |
| task.Configure(processManager, true); | |
| task.OnStartProcess += proc => | |
| { | |
| foreach (var line in lines) | |
| { | |
| proc.StandardInput.WriteLine(line); | |
| } | |
| proc.StandardInput.Close(); | |
| }; | |
| return task; |
For that reason, I think that we need an asynchronous BeginRead.
Please tell me if there is a better way.
| Process.BeginErrorReadLine(); | ||
| { | ||
| errorReset.Reset(); | ||
| Process.StandardError.BaseStream.BeginRead( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do the same thing here.
| if (Process.StartInfo.RedirectStandardOutput) | ||
| outputReset.WaitOne(); | ||
| if (Process.StartInfo.RedirectStandardError) | ||
| errorReset.WaitOne(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That way we no longer need these ManualResetEvent objects.
…iew-with-non-ascii-characters-fixes-124
…rs-in-history-view-with-non-ascii-characters-fixes-124 # Conflicts: # src/GitHub.Api/NewTaskSystem/ProcessTask.cs
|
@shiena there is another branch based off this, could you test it out for me. https://github.com/github-for-unity/Unity/tree/fixes/returning-lines-sooner |
|
LFS Verification checks are preventing me from pushing to your repo |
|
@StanleyGoldman Japanese also displayed correctly for that branch. |
# Conflicts: # src/GitHub.Api/NewTaskSystem/ProcessTask.cs
|
Edited the pull request description to show what this PR depends on |
|
@StanleyGoldman I think that #35 has also been fixed. |
|
You may be right, let's see |
|
You are correct. |
| if (token.IsCancellationRequested) | ||
| var outputStream = Process.StandardOutput.BaseStream; | ||
| var outputBuffer = new byte[bufferSize]; | ||
| var outputEncoding = Process.StartInfo.StandardOutputEncoding ?? Console.Out.Encoding; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can Process.StartInfo.StandardOutputEncoding ever be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could not be null by tracing the call hierarchy. So delete the null check.
| } | ||
| var errorStream = Process.StandardError.BaseStream; | ||
| var errorBuffer = new byte[bufferSize]; | ||
| var errorEncoding = Process.StartInfo.StandardErrorEncoding ?? Console.Error.Encoding; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about Process.StartInfo.StandardErrorEncoding ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also delete null check.
|
@StanleyGoldman @shana Even if you need the git command line option, this pull request is redundant, so I would like to create another pull request. |
|
@shiena Yup, we were literally just discussing that 10 minutes ago and came to the same conclusion 😄 👍 |
|
Hey @shiena we were about to say the same thing to you... |
fixes #124
fixes #35
Depends on:
I replaced the reading of standard output from asynchronous to synchronous to eliminate garbled characters.
Synchronous reading of both standard output and standard error may cause deadlock. So I replaced standard output only.
Reference: https://stackoverflow.com/questions/7160187/standardoutput-readtoend-hangs
Also, I'm worried about whether performance will be bad.