Victim #552072 of property inlining bug reporting, sir...

Victim #552072 of property inlining bug reporting, sir...

Old forum URL: forums.lhotka.net/forums/t/1167.aspx


Izhido posted on Friday, September 08, 2006

Hi everyone!

Just wanted to say, "me too". I was hit by the (most definately .NET 2.0) bug where, if you don't specifically mark your business properties as <MethodImpl(NoInlining)>, your validation/authorization rules might be reported as broken, when they really aren't, using "Release" versions of your binaries (instead of the "Debug" ones).

Fortunately, I was using a code generation tool for my business layer, so making the change was no problem at all. And it worked Smile [:)] (for me, at least). On a side note, since I was using VB 2005 Express, this implied (just to be really sure) manually modifying the .vbproj files of my projects, with Notepad, to make them actually generate the "Debug" and "Release" versions of the binaries into specific, clearly marked directories, and to rebuild the references to make sure the UI project was using the "Release" biz-layer assembly. Oh, how I wish I could get my hands on VS 2005 Pro...

Y'know, I think this is becoming more and more of an important issue. This bug is of the kind of bugs that will invariably go unnoticed during the development stage of a project, and when detected it might be too late for a "quick fix" (except if that "quick fix" becomes deploying "Debug"-only versions of the components Tongue Tied [:S] ). Of course, Rocky wouldn't possibly know that this was going to happen; if you declare a method with <MethodImpl(NoInlining)>, just like PropertyChanged() method was, the JIT compiler should at least become aware of that, and try to take precautions when compiling code that contains such attributed method calls.

The thing here is, since .NET 2.0 was already released as RTM, and everyone is using it, well, anyone using CSLA.NET 2.0.(0/1/2/3/...) will be hit by this bug sooner or later. And, to be honest, it took me a while to find out why suddenly my application was rejecting every single customer, product, warehouse, you name it, that was being added using my input forms when I deployed it at the testing machine, when the very same exact code (or, at least, I thought so) was working just fine in my development computer!

Rocky, I know it's not your fault. You did what it seemed to be the right thing when creating the PropertyHasChanged() method. But something else outside your code broke it. And the workarounds for that particularly ugly bug are either ugly (deploying "Debug" assemblies) or will require a long time to implement (including <MethodImpl(NoInlining)> into every single business property). What I want to ask of you is, please, write something about it. Write any thoughts you have about it, but please, do it. Write about it in your blog, or at your web site, or in a place that everyone will see. Everyone using your excellent framework is also visiting your (also excelent) web site, and reading your (also excellent) web blog. You're the Commander in Chief of all things CSLA-related. Please, at least issue a warning telling us that this particular bug might happen to us some day. And that we should take precautions. Please!!!

Ugh... my head... my stomach hurts so bad Tongue Tied [:S]Big Smile [:D]. I'm conscious that the previous paragraph sounded like I was demanding you, Rocky, to do something. But that wasn't the idea. That idea alone is going to make me sick, I'm sure. What I wanted is to make sure future generations of users of CSLA.NET wouldn't have to face these issues on their own. I'm pretty sure CSLA.NET usage is rapidly growing, and it will continue to be for a while. And it's not without a reason.
Bugs, or not bugs, I think CSLA.NET is the most beautifully written business layer framework. And the most efficient for it's primary job. So, please, refer to this issue sometime soon. I can almost guarantee we all will be happy to hear from you talking about it, and having a chance to remedy things soon.

Thanks for your patience reading this! Smile [:)]

ajj3085 replied on Friday, September 08, 2006

Izhido:
On a side note, since I was using VB 2005 Express, this implied (just to be really sure) manually modifying the .vbproj files of my projects, with Notepad, to make them actually generate the "Debug" and "Release" versions of the binaries into specific, clearly marked directories, and to rebuild the references to make sure the UI project was using the "Release" biz-layer assembly. Oh, how I wish I could get my hands on VS 2005 Pro...


I played with the Express versions a bit, but didn't have a problem with assemblies not going into bin\debug or bin\release.  Of course you have to enable a bunch of options to get the Debug / Release options on yoru toolbar, but it could do it.  I think its over now, but there was a offer were if you watched three Asp.Net for Java webiniars, you could get VS 2005 Standard for free.   That's how I got my copy.  You may want to see if there's something else like that.

Izhido:
Y'know, I think this is becoming more and more of an important issue. This bug is of the kind of bugs that will invariably go unnoticed during the development stage of a project, and when detected it might be too late for a "quick fix" (except if that "quick fix" becomes deploying "Debug"-only versions of the components Tongue Tied [:S] ). Of course, Rocky wouldn't possibly know that this was going to happen; if you declare a method with <MethodImpl(NoInlining)>, just like PropertyChanged() method was, the JIT compiler should at least become aware of that, and try to take precautions when compiling code that contains such attributed method calls.


Well, it depends on if you use the no parameters overload.  I never did, because I always wanted to be explicit.  At any rate you'd ideally have unit tests which could catch this ealier in your development cycle.  This is one of the reasons why my build server only builds and runs tests on Release settings; I want it to test that my Release code is actually releasable. 

Now if you can't do unit tests for whatever reason, I understand, so maybe this method needs to be axed all together, or at the very least a comment in the <remarks /> tag will do warning about the inlining.  Of course it'd be helpful if we had a .Net 2.0 documenation tool, but Sandcastle isn't out of beta and sadly NDoc is dead.

Izhido:
The thing here is, since .NET 2.0 was already released as RTM, and everyone is using it, well, anyone using CSLA.NET 2.0.(0/1/2/3/...) will be hit by this bug sooner or later. And, to be honest, it took me a while to find out why suddenly my application was rejecting every single customer, product, warehouse, you name it, that was being added using my input forms when I deployed it at the testing machine, when the very same exact code (or, at least, I thought so) was working just fine in my development computer!


Not everyone; I've always specified the property name.  It should be better documented though, if its not already.

Izhido:
Rocky, I know it's not your fault. You did what it seemed to be the right thing when creating the PropertyHasChanged() method. But something else outside your code broke it. And the workarounds for that particularly ugly bug are either ugly (deploying "Debug" assemblies) or will require a long time to implement (including <MethodImpl(NoInlining)> into every single business property). What I want to ask of you is, please, write something about it. Write any thoughts you have about it, but please, do it. Write about it in your blog, or at your web site, or in a place that everyone will see. Everyone using your excellent framework is also visiting your (also excelent) web site, and reading your (also excellent) web blog. You're the Commander in Chief of all things CSLA-related. Please, at least issue a warning telling us that this particular bug might happen to us some day. And that we should take precautions. Please!!!


Actually I'm pretty sure he did write about this issue in his blog.  Smile [:)]  And there's a thread on this forum about this issue.  Perhaps an errata to the book itself is called for, and a <remarks /> for that particular overload that explains this issue is warranted.

Izhido:
Ugh... my head... my stomach hurts so bad Tongue Tied [:S]Big Smile [:D].


Heh... I've felt like that at times because of something I was coding.  Hope you feel better.

Anyway, just my $0.16 (adjusted for inflation).

Andy

RockfordLhotka replied on Friday, September 08, 2006

I appreciate, and share, your frustration...

Fwiw, I did write about it on my web site when the issue was first discovered, so the issue is documented along with the solution, and the current versions of the snippets/templates include the attribute.



Izhido replied on Friday, September 08, 2006

Thanks a lot! Big Smile [:D]Big Smile [:D]Big Smile [:D] I can't believe I didn't see the article... got a little lost since the web site redesign. Again, thanks!!!

RobKraft replied on Tuesday, September 18, 2007

I have to pipe in on this thread to share a case where noinlining appears not to work.  We are going to start passing in parameters by name.  We are on .Net 2.0 and CSLA 2.14.  This code works for about 100 of our properties, but seems to not work for 1 or 2.  There is no pattern to the 1 or 2 where it fails, they are just like all the others.  Even though we specify noinlining, in a few cases the method appears to get inlined.

Here is our code that succeeds:

public Int16 SequenceNum

{get { return _SRN_SEQ; }

set {SetPropertyValue<Int16>(ref _SRN_SEQ, value, 0); }}

Here is our code that fails:

public Int16 Sequence

{ get { return _SR_SEQ; }

 set {SetPropertyValue<Int16>(ref _SR_SEQ, value, 0); }}

And here is the method they both call.

   1:          [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]

   2:          protected bool SetPropertyValue<V>(ref V memberVariable, V newValue, V ValueIfNothing)
   3:          {
   4:              bool result = false;
   5:              if (memberVariable == null && newValue == null)
   6:              {
   7:                  result = false; //Nothing changed.  memberVariable is still nothing.
   8:              }
   9:              else if (memberVariable == null && newValue != null)
  10:              {
  11:                  result = true; //new value passed in; memberVariable was null - make the change.
  12:              }
  13:              else if (memberVariable != null && newValue == null)
  14:              {
  15:                  newValue = ValueIfNothing; //newValue = null, so reset newValue to the ValueIfNothing Value.
  16:                  result = true;
  17:              }
  18:              else if (memberVariable != null && newValue != null)
  19:              {
  20:                  if (memberVariable.Equals(newValue))
  21:                  {
  22:                      result = false; //newValued, but no change.
  23:                  }
  24:                  else
  25:                  {
  26:                      result = true;  //newValued, changed newValue.
  27:                  }
  28:              }
  29:   
  30:              if (result == true)
  31:              {
  32:                  string propName = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().Name.Substring(4);
  33:                  if (CanWriteProperty(propName, true))   // checks user's authorization
  34:                  {
  35:                      memberVariable = newValue;
  36:                      PropertyHasChanged(propName);
  37:                  }
  38:                  else
  39:                  {
  40:                      result = false;
  41:                  }
  42:              }
  43:              return result;
  44:          }  //End function

ajj3085 replied on Wednesday, September 19, 2007

Are the properties themselves also set not to inline?

RobKraft replied on Wednesday, September 19, 2007

No, the properties were NOT set to inlining.  I tried changing the properties that call my SetPropertyValue to also use NOInlining and that fixed my problem.  Thanks for the tip!

Copyright (c) Marimer LLC