从.Net框架Bug的提交到修复代码成功合并到.NET CoreFX主线
從發(fā)現(xiàn).NET Framework中SmtpClient的Bug并拿出解決方案,然后給微軟開發(fā)者社區(qū)提交Bug開始,總共耗時一個多月,對Bug修復(fù)的代碼最終被采納,現(xiàn)已合并到.NET Core Libraries (CoreFX)主線中。
修復(fù)記錄https://github.com/dotnet/corefx/commit/94b1f1eae84fd4823cfa2bbdde6fc87c46b57908
雖然對Bug修復(fù)實際生效的代碼只有20個字符,但意義重大,這個Bug不遇上一點事沒有,遇上了不對框架開刀是非常棘手的,而且備受折磨也稍微有點難摸得清頭腦。
相關(guān)詳情見我的另外一篇博客《記錄一次.Net框架Bug發(fā)現(xiàn)和提交過程:.Net Framework和.Net Core均受影響》
問題描述
我們用SmtpClient的SendAsync、?SendMailAsync異步方法發(fā)送郵件,并且要求使用DeliveryFormat?=?SmtpDeliveryFormat.SevenBit?格式來編碼中文內(nèi)容,本來預(yù)期是郵件內(nèi)容中帶中文的Subject、Attachments file name?都會進(jìn)行Base64編碼。
但實際結(jié)果是:如果郵件服務(wù)器支持SMTPUTF8擴(kuò)展,那么異步發(fā)送SevenBit郵件并不會進(jìn)行Base64編碼,同步方法沒有此問題。
問題根源
原因是在SmtpClient.SendMailCallback方法中,message.BeginSend?allowUnicode參數(shù)直接使用的ServerSupportsEai,而不是統(tǒng)一的IsUnicodeSupported()。
private void SendMailCallback(IAsyncResult result){ ......_message.BeginSend(_writer, DeliveryMethod != SmtpDeliveryMethod.Network, ServerSupportsEai, new AsyncCallback(SendMessageCallback), result.AsyncState); ......}把ServerSupportsEai改成IsUnicodeSupported()問題解決。就這20個字符的改動~
另外附對現(xiàn)有帶Bug的.Net框架修復(fù)方法
比如使用的.NET Framework 4.7.2,純天然原生自帶此Bug,我們可以用我們的代碼修復(fù)它。
最開始測試時以為此方法無效,沒想到是Hook錯了地方,換到最深層次調(diào)用地方,一抓一個準(zhǔn)。
使用DotNetDetour庫對.Net框架內(nèi)方法進(jìn)行Hook,找出SmtpClient.ServerSupportsEai最結(jié)果最終是從SmtpConnection.ServerSupportsEai得來的,也許是C#編譯后把整個調(diào)用過程都優(yōu)化掉了,變成了取值的地方直接調(diào)用的SmtpConnection中的方法,導(dǎo)致Hook前面的方法都是不會被執(zhí)行,Hook?SmtpConnection.ServerSupportsEai一抓一個準(zhǔn)。
附上Hook代碼:
public class Hook : IMethodMonitor { ? ?public bool ServerSupportsEai {[] ? ?
? ?get {Console.WriteLine("Hook"); ? ? ?
? ? ? ? ?? ? ?return !true?org():false;//什么情況下要Hook? AsyncLocal和CallContext上下文為什么在這里傳不進(jìn)來?}}[]
?? ?public bool org() { ? ? ?
?? ? ?return false;} }
另外引出了另外一個折磨人Bug,異步環(huán)境下,ServerSupportsEai的調(diào)用棧中上下文怎么會丟失?難道哪里使用了類似ThreadPool.UnsafeXXX這種效果?我們沒法通過CallContext(AsyncLocal)給Hook代碼傳參數(shù),只能寫死,不管調(diào)用方要不要修改返回值,都只能得到修改后的結(jié)果,尷尬不尷尬。
總結(jié)
以上是生活随笔為你收集整理的从.Net框架Bug的提交到修复代码成功合并到.NET CoreFX主线的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: eShopOnContainers 看微
- 下一篇: .net core i上 K8S(四).
