• (cs)

    What is the point of adding code that will bypass the 29.02 date and obviously not testing it, to be sure that software will not blow up the universe when such date occurs, instead of simple testing what happens on 29.02?

  • frost (unregistered) in reply to Iwamori

    Just what in hell is the issue in having a log entry on feb 29??

  • (cs) in reply to frost
    frost:
    Just what in hell is the issue in having a log entry on feb 29??
    Read the comments in the code.

    The original developer didn't know that it would be OK, so he wrote some bogus code in a misguided attempt to avoid it.

    And catch(...) is arguably the most WTFy part. VC++6 has the charming habit of (by default) catching segfaults and assorted other Windowsy nastiness in catch(...) blocks, resulting in uncrashable programs, sure, but also making diagnosis very difficult outside of a debugger.

  • Greg (unregistered)

    Looks like C++ written by a java programmer.

  • RFox (unregistered)

    while(!done) { Frist f = new Frist; }

    a bit late but

  • WTFy (unregistered) in reply to Greg

    Exactly what I was thinking. I've had a deal with a lot of C++ code written by Java programmers who think that C++ is essentially the same as Java. Leads to some very inefficient and, like this case, potentially dangerous code.

  • faoileag (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    And catch(...) is arguably the most WTFy part.

    No. The most WTFy part is running

    while(currentDate->dayOfYear() == 60) { currentDate = new Date(); }

    all day long on February 29th.

    There's not even a sleep() in that loop! On the 29th of February, that server is pwned by a 24 hour long "while true do".

  • PB (unregistered)

    Empty Catch statements are the root of all evil.

  • Kent Lenning (unregistered) in reply to faoileag
    faoileag:
    Steve The Cynic:
    And catch(...) is arguably the most WTFy part.

    No. The most WTFy part is running

    while(currentDate->dayOfYear() == 60) { currentDate = new Date(); }

    all day long on February 29th.

    There's not even a sleep() in that loop! On the 29th of February, that server is pwned by a 24 hour long "while true do".

    Waiting for a date/time with a busy-wait-loop is common in small embedded systems. On a multicore server, one process doing this would probably not be noticeable at all. Back when desktops had a single core this would be very noticeable.

    Maybe this was written by a former embedded systems programmer, who picked up the bad habits Java encourages.

    The most amusing thing is that if the server had enough virtual memory, everything would just slow down as it started to thrash, and maybe the allocation rate of this code would go low enough to make it to the next day... whereupon everything mysteriously goes back to normal again.

  • Kristof Provost (unregistered)
    Since "if we failed we need to try again until we succeed", it responds to the out-of-memory exception by... continuing to loop and hold onto its memory, bringing every server running the processing job to its RAM-starved knees.

    Pet peeve. It almost certainly won't do that. Modern operating systems overallocate memory. They hand out virtual memory space to processes without backing them with real memory (there's a metaphore for the modern banking system in there somewhere). The physical memory isn't allocated unil you actually write to the virtual memory.

    When you actually run out of physical memory the kernel ends up having to pick a process to kill to free some memory.

    In other words: no execption. The kernel would just kill this process.

  • Herr Otto Flick (unregistered) in reply to PB
    PB:
    Empty Catch statements are the root of all evil.

    No, ignoring RAII and not sleeping is the root of all evil. I think the earlier commenter had it spot on, C++ written by a Java weenie, there is absolutely no need to create the date on the heap in the first place.

  • Smug Unix User (unregistered)

    Dates are hard for most programmers to get.

  • (cs) in reply to Kristof Provost
    Kristof Provost:
    bringing every server running the processing job to its RAM-starved knees.

    When you actually run out of physical memory the kernel ends up having to pick a process to kill to free some memory.

    In other words: no execption. The kernel would just kill this process.

    Was thinking the same... but then again, it might be one of those servers set up with tons of swap memory to be used as extra RAM. Extra-slow RAM, might I say.

    That's why I run my servers with no swap. I'd rather have my processes die, than the whole server run 1000 times slower.

  • cyborg (unregistered) in reply to Iwamori

    I really need to know what on Earth the original developer was even thinking in their belief this code would be necessary. That is definitely TRWTF.

  • noname (unregistered) in reply to Kristof Provost
    Kristof Provost:
    Since "if we failed we need to try again until we succeed", it responds to the out-of-memory exception by... continuing to loop and hold onto its memory, bringing every server running the processing job to its RAM-starved knees.

    Pet peeve. It almost certainly won't do that. Modern operating systems overallocate memory. They hand out virtual memory space to processes without backing them with real memory (there's a metaphore for the modern banking system in there somewhere). The physical memory isn't allocated unil you actually write to the virtual memory.

    When you actually run out of physical memory the kernel ends up having to pick a process to kill to free some memory.

    In other words: no execption. The kernel would just kill this process.

    The memory is written because there is a Date instance created in that memory.

  • tragomaskhalos (unregistered)

    Date *currentDate = new Date(); ???

    Fuggin' idiot

  • Jess (unregistered)

    So I wonder what happened on March 1, 2010? It was a weekday (Monday) so shouldn't they have found/fixed this then?

  • (cs) in reply to Kent Lenning
    Kent Lenning:
    faoileag:
    Steve The Cynic:
    And catch(...) is arguably the most WTFy part.

    No. The most WTFy part is running

    while(currentDate->dayOfYear() == 60) { currentDate = new Date(); }

    all day long on February 29th.

    There's not even a sleep() in that loop! On the 29th of February, that server is pwned by a 24 hour long "while true do".

    Waiting for a date/time with a busy-wait-loop is common in small embedded systems. On a multicore server, one process doing this would probably not be noticeable at all. Back when desktops had a single core this would be very noticeable.

    Maybe this was written by a former embedded systems programmer, who picked up the bad habits Java encourages.

    The most amusing thing is that if the server had enough virtual memory, everything would just slow down as it started to thrash, and maybe the allocation rate of this code would go low enough to make it to the next day... whereupon everything mysteriously goes back to normal again.

    My company has enough bureaucratic process that developers wouldn't actually get a chance to look at this until March 2nd or 3rd, at which point we'd simply close the bug as "cannot reproduce". It's a good system if you plan on not working here for another 4 years...

  • not an anon (unregistered) in reply to cyborg
    cyborg:
    I really need to know what on Earth the original developer was even thinking in their belief this code would be necessary. That is definitely TRWTF.

    QFT. The "dev" who wrote this code needs to have a Long Count dropped on their head a few times.

  • Kristof Provost (unregistered) in reply to noname
    The memory is written because there is a Date instance created in that memory.
    Of course. That's not my point. My point is that instead of getting an exception from 'new' you'd get terminated by the out-of-memory killer.
  • ¯\(°_o)/¯ I DUNNO LOL (unregistered)
    if (lastDigit(currentDate->year()) == 0 || lastDigit(currentDate->year()) == 4 || lastDigit(currentDate->year()) == 8))
    Isn't this the exact same crap that caused the PS3 date problem? The only difference is that in the case of the PS3, this WTF was actually in the silicon of the clock chip, causing it to think 2010 was a leap year.
  • (cs) in reply to ¯\(°_o)/¯ I DUNNO LOL
    ¯\(°_o)/¯ I DUNNO LOL:
    if (lastDigit(currentDate->year()) == 0 || lastDigit(currentDate->year()) == 4 || lastDigit(currentDate->year()) == 8))
    Isn't this the exact same crap that caused the PS3 date problem? The only difference is that in the case of the PS3, this WTF was actually in the silicon of the clock chip, causing it to think 2010 was a leap year.

    I was beginning to wonder if I was misreading the code when it looked to me like 2010, 2014, and 2018 were considered leap years.

    Add that one to the stack of WTFs.

  • (cs) in reply to Kent Lenning
    Kent Lenning:
    The most amusing thing is that if the server had enough virtual memory, everything would just slow down as it started to thrash, and maybe the allocation rate of this code would go low enough to make it to the next day... whereupon everything mysteriously goes back to normal again.
    Actually, it wouldn't go back to normal - that memory would still be allocated and not able to be deallocated (because the code deliberately forgot where it was). Also, if this is a 32-bit process on a 64-bit system, it might well be able to guzzle up almost 4GB without (a) running out of virtual address space and (b) thrashing very much, meaning that it might be able to really run out of virtual address space before thrashing the machine. How long would 4GB take to allocate in Date object-sized pieces? ...
  • confusopoly (unregistered) in reply to Kristof Provost
    Kristof Provost:
    The memory is written because there is a Date instance created in that memory.
    Of course. That's not my point. My point is that instead of getting an exception from 'new' you'd get terminated by the out-of-memory killer.
    Correction: SOMEONE would get terminated by the OOM killer. At least Linux uses a heuristic to pick a victim based on a "badness" score instead
  • (cs) in reply to Smug Unix User
    Smug Unix User:
    Dates are hard for most programmers to get.
    Dates are hard, full stop. 99% of humans don't have to deal with dates in their full unholy madness. Programmers do.
  • Kristof Provost (unregistered) in reply to confusopoly
    confusopoly:
    Correction: SOMEONE would get terminated by the OOM killer. At least Linux uses a heuristic to pick a victim based on a "badness" score instead

    True, although if you've just spent the last X seconds eating up all of the memory it's pretty likely that the heuristic will pick you.

  • (cs) in reply to PB
    PB:
    Empty Catch statements are the root of all evil.

    I would consider them harmful.

    Also, Try statements inside a loop can lead to interesting issues. Ever seen a 10k+ iteration loop with a Try statement that logs verbosely on exceptions fail? It's not fun.

  • (cs) in reply to Kristof Provost
    Kristof Provost:
    Since "if we failed we need to try again until we succeed", it responds to the out-of-memory exception by... continuing to loop and hold onto its memory, bringing every server running the processing job to its RAM-starved knees.

    Pet peeve. It almost certainly won't do that. Modern operating systems overallocate memory. They hand out virtual memory space to processes without backing them with real memory (there's a metaphore for the modern banking system in there somewhere). The physical memory isn't allocated unil you actually write to the virtual memory.

    When you actually run out of physical memory the kernel ends up having to pick a process to kill to free some memory.

    In other words: no execption. The kernel would just kill this process.

    I was thinking of airlines that oversell flights.

  • ih8u (unregistered) in reply to Jess
    Jess:
    So I wonder what happened on March 1, 2010? It was a weekday (Monday) so shouldn't they have found/fixed this then?

    Yeah, there's no way this code change was checked-in or deployed between 2010 and 2014, so obviously it ran before with no problems.

    Also, I still don't see why it doesn't get correct leap years. Leap years are div by 4. 24 ... yep, 48 ... yep, 60 ... yep. Year ends in 0, 4 and 8 check out.

    Code change accepted. Move along.

    Captcha: I saluto your analytical skillz (definitely with a 'z')

  • (cs) in reply to Jess
    Jess:
    So I wonder what happened on March 1, 2010? It was a weekday (Monday) so shouldn't they have found/fixed this then?

    Presumably the code was written sometime after March 1 2010 but before February 29 2012.

  • Doodpants (unregistered) in reply to Zylon
    Zylon:
    Smug Unix User:
    Dates are hard for most programmers to get.
    Dates are hard, full stop. 99% of humans don't have to deal with dates in their full unholy madness. Programmers do.
    I think you missed the pun.
  • (cs)

    Yeah, whoever wrote this was a brain-dead moron, but even modern languages don't seem to have built-in functions to deal with leap years properly.

    The algorithms involved aren't particularly complex, but both Java and .NET are both lacking in utility functions which accurately handle them... (the scripting oriented languages like python, ruby or dare i say it perl may be better at this, but i haven't tried, maybe Ben could even give us a solution in Go!)

    For example, try writing a function to tell from a date of birth of someone is over the legal drinking age in either Java or C#. It sounds easy, but the utility function you'll probably reach for is strangely absent.

  • (cs) in reply to Steve The Cynic
    Steve The Cynic:
    ...How long would 4GB take to allocate in Date object-sized pieces? ..."

    Not very long at all, maybe 10 seconds (at most) on a 2ghz class VM using the standard C++ heap manager. If it were done in a tight loop. The standard string class in C++ can exhaust memory even faster, which is a fun problem to debug when people like to concatenate the current error with the previous error, recursively and so fourth.

  • XXXXX (unregistered)

    How is this possibly legacy code? This should have crashed the servers every four years. Didn't this bug happen in 2010? Unless 3 year old software is considered legacy now?

    Is this legacy in the sense of "We wrote it once and never change any code that has been written"?

  • Anonymous') OR 1=1 (unregistered) in reply to Steve The Cynic
    Steve The Cynic:
    frost:
    Just what in hell is the issue in having a log entry on feb 29??
    Read the comments in the code.

    The original developer didn't know that it would be OK, so he wrote some bogus code in a misguided attempt to avoid it.

    And catch(...) is arguably the most WTFy part. VC++6 has the charming habit of (by default) catching segfaults and assorted other Windowsy nastiness in catch(...) blocks, resulting in uncrashable programs, sure, but also making diagnosis very difficult outside of a debugger.

    If anyone's still using VC++6 these days, they deserve what they get. Modern versions of Visual Studio only convert SEH exceptions (like access violations) into C++ exceptions if you compile with the /EHa option, which is not enabled by default.

    I still wouldn't ever recommend using that option, though — in the rare instances where you do need to catch access violations (like if you're writing a crash dump handler), you should use the normal SEH constructs __try/__except to deal with them, not C++'s catch.

  • (cs) in reply to Anonymous') OR 1=1
    Anonymous') OR 1=1:
    If anyone's still using VC++6 these days, they deserve what they get. Modern versions of Visual Studio only convert SEH exceptions (like access violations) into C++ exceptions if you compile with the /EHa option, which is not enabled by default.

    I still wouldn't ever recommend using that option, though — in the rare instances where you do need to catch access violations (like if you're writing a crash dump handler), you should use the normal SEH constructs __try/__except to deal with them, not C++'s catch.

    If anyone is still writing new business logic in C++ these days they deserve what they get.

    Despite the best efforts of so many people, it's not platform independent, it's a vulnerability vector, and provides the programmer with so many ways to shoot themselves in the foot (or even the head), even with great source control and a rigorous peer review system, even some intern can sneak something in that will bring you're production environment to a screeching halt.

    Pro Tip, slip a sneaky "new" statement into the copy constructor (but not the assignment operator), and then forget to de-allocate it in the virtual destructor (which is only ever called from a base class pointer), it'll confuse the shit out of everyone.

    Even better, put random #pragma pack statements into header files which are #included in multiple .cpp files. This will create bugs which are almost impossible to debug.

  • (cs) in reply to caffiend
    caffiend:
    Yeah, whoever wrote this was a brain-dead moron, but even modern languages don't seem to have built-in functions to deal with leap years properly.

    The algorithms involved aren't particularly complex, but both Java and .NET are both lacking in utility functions which accurately handle them... (the scripting oriented languages like python, ruby or dare i say it perl may be better at this, but i haven't tried, maybe Ben could even give us a solution in Go!)

    For example, try writing a function to tell from a date of birth of someone is over the legal drinking age in either Java or C#. It sounds easy, but the utility function you'll probably reach for is strangely absent.

    heh

  • Someone else (unregistered) in reply to caffiend
    caffiend:
    ...but the utility function you'll probably reach for is strangely absent.

    I'd just as soon reach for NodaTime/JodaTime.

  • damnum (unregistered) in reply to XXXXX
    XXXXX:
    How is this possibly legacy code? This should have crashed the servers every four years. Didn't this bug happen in 2010? Unless 3 year old software is considered legacy now?
    The module itself is probably older than that if it's described as "legacy", but that doesn't mean the quoted code has always been there.
  • (cs) in reply to chubertdev
    chubertdev:

    Unless you want to write a loop and implement the logic you're self, you're out of luck.

    What i was referring to is the absence of methods like.

    TimeSpan.Years or TimeSpan.Months

    which is what you get from the arithmetic operators on DateTime objects in C#, I'm pretty sure Java is similar. Oh, no wait, in Java you get to chose whether you want to get you're results using the Gregorian calender or the Julian calender (because the flawed date-keeping system used in ancient Rome might be useful to me).

    I'm sorry, I shouldn't rant, the only thing worse than computational representations of date & time is how to handle daylight savings.

  • C-Derb (unregistered) in reply to caffiend
    caffiend:
    For example, try writing a function to tell from a date of birth of someone is over the legal drinking age in either Java or C#. It sounds easy, but the utility function you'll probably reach for is strangely absent.

    It actually ain't that hard, since most societies with age related drinking laws are measured in years, not days, of age. For example, in the United States*, legal drinking age is 21 years old, not 7,665 days old.

    *Disclaimer: I'm admittedly ignorant about each individual state's laws on drinking. If there's a state that has a lower age limit, suck it.

  • (cs) in reply to Someone else
    Someone else:

    I'd just as soon reach for NodaTime/JodaTime.

    And then spend the same amount of time trying to get any ORM to store those objects in a database without completely screwing up you're domain model.

  • (cs) in reply to C-Derb
    C-Derb:
    It actually ain't that hard, since most societies with age related drinking laws are measured in years, not days, of age. For example, in the United States*, legal drinking age is 21 years old, not 7,665 days old.

    Yes... that's my point.

    You'd expect to be able to write

    if ((DateTime.Now - person.DOB).Years > 21) DirnkMachine.Despence();

    But there is no "Years" method. I'm not saying it's hard to implement, it's not, I'm just surprised it's not part of the standard libraries of the most commonly used languages in use.

  • C-Derb (unregistered) in reply to caffiend
    caffiend:
    C-Derb:
    It actually ain't that hard, since most societies with age related drinking laws are measured in years, not days, of age. For example, in the United States*, legal drinking age is 21 years old, not 7,665 days old.

    Yes... that's my point.

    You'd expect to be able to write

    if ((DateTime.Now - person.DOB).Years > 21) DirnkMachine.Despence();

    But there is no "Years" method. I'm not saying it's hard to implement, it's not, I'm just surprised it's not part of the standard libraries of the most commonly used languages in use.

    This C# doesn't work for you?
    if(person.DOB.AddYears(21) < DateTime.Now)
    {
      DrinkMachine.Despence();
    }
    
  • Anonymous') OR 1=1 (unregistered) in reply to C-Derb
    C-Derb:
    *Disclaimer: I'm admittedly ignorant about each individual state's laws on drinking. If there's a state that has a lower age limit, suck it.

    The US has a federal drinking age of 18, but states are free to impose their own drinking age. Because of the National Minimum Drinking Age Act if 1984, however, a state gets 10% less federal highway funding if it sets a drinking age below 21, so every state sets it as 21 to get that highway funding.

    But US territories aren't states and don't have federally funded highways (I believe), so they don't care about that and set the drinking age at 18. So if you go any territories like the US Virgin Islands, you're free to drink at 18.

  • (cs) in reply to C-Derb
    C-Derb:
    This C# doesn't work for you?
    if(person.DOB.AddYears(21) < DateTime.Now)
    {
      DrinkMachine.Despence();
    }
    

    Actually it does, I'm man enough to admit when I'm wrong. You've just helped me delete 30 or so lines of code, and despite the embarrassment on here, I'm happy with that. Didn't know that was there.

    Thanks :)

  • C-Derb (unregistered) in reply to caffiend
    caffiend:
    C-Derb:
    This C# doesn't work for you?
    if(person.DOB.AddYears(21) < DateTime.Now)
    {
      DrinkMachine.Despence();
    }
    

    Actually it does, I'm man enough to admit when I'm wrong. You've just helped me delete 30 or so lines of code, and despite the embarrassment on here, I'm happy with that. Didn't know that was there.

    Thanks :)

    If I were a drinking man, I'd let you buy me a drink! As it is, that you and I didn't get into a flame war is TRWTF.

  • (cs) in reply to Anonymous') OR 1=1

    Yeah, was going to say this:

    Anonymous') OR 1=1:
    C-Derb:
    *Disclaimer: I'm admittedly ignorant about each individual state's laws on drinking. If there's a state that has a lower age limit, suck it.

    The US has a federal drinking age of 18, but states are free to impose their own drinking age. Because of the National Minimum Drinking Age Act if 1984, however, a state gets 10% less federal highway funding if it sets a drinking age below 21, so every state sets it as 21 to get that highway funding.

    But US territories aren't states and don't have federally funded highways (I believe), so they don't care about that and set the drinking age at 18. So if you go any territories like the US Virgin Islands, you're free to drink at 18.

  • (cs) in reply to caffiend
    caffiend:
    chubertdev:

    Unless you want to write a loop and implement the logic you're self, you're out of luck.

    What i was referring to is the absence of methods like.

    TimeSpan.Years or TimeSpan.Months

    which is what you get from the arithmetic operators on DateTime objects in C#, I'm pretty sure Java is similar. Oh, no wait, in Java you get to chose whether you want to get you're results using the Gregorian calender or the Julian calender (because the flawed date-keeping system used in ancient Rome might be useful to me).

    I'm sorry, I shouldn't rant, the only thing worse than computational representations of date & time is how to handle daylight savings.

    Whatever, I'm not even sure why you brought that up. All I know is that based on your posts, there's a very good chance that your code will appear in an article on this site, as proven by the comments above me.

  • (cs) in reply to C-Derb
    C-Derb:
    caffiend:
    C-Derb:
    It actually ain't that hard, since most societies with age related drinking laws are measured in years, not days, of age. For example, in the United States*, legal drinking age is 21 years old, not 7,665 days old.

    Yes... that's my point.

    You'd expect to be able to write

    if ((DateTime.Now - person.DOB).Years > 21) DirnkMachine.Despence();

    But there is no "Years" method. I'm not saying it's hard to implement, it's not, I'm just surprised it's not part of the standard libraries of the most commonly used languages in use.

    This C# doesn't work for you?
    if(person.DOB.AddYears(21) < DateTime.Now)
    {
      DrinkMachine.Despence();
    }
    

    Should be ">="

    Also, what happens when the DOB is stored with time? I was born at 11:46pm, but I was able to drink before that time on my 21st birthday.

    Addendum (2014-09-17 19:49):

    • <=

    not >=

Leave a comment on “Failure to Leap”

Log In or post as a guest

Replying to comment #:

« Return to Article