CodeSOD: A Deeply Nested Mystery |
As any competent developer knows, not all Web browsers were created equal. In a stew of standards, drafts, vendor extensions, and JavaScript engine quirks, each of them can behave a little differently under various circumstances. Many people tried to resolve this situation, but "creative" coders are always one step ahead, finding new and amusing ways to mandate the dreaded "runs only under Internet Explorer 6" popup on their webpages.
This time, our submitter found out that his bus timetable was working just fine on Safari:
Under Firefox, however, it was curiously missing one of the schedules:
Is it a JS compatibility hack gone wrong? he wondered. Maybe a badly-placed -webkit-
prefix? Curious, he checked the source.
It was neither. Instead, the author of the code just really, really, really wanted the link to be blue:
Route 10 - B LINE
That, however, triggered a rather obscure glitch in Firefox and the browser simply gave up on rendering 158 nested tags.
And even though our submitter ultimately missed his bus, he at least learned a valuable life lesson: when you push things too hard, they often break.
Метки: CodeSOD |
Dynamic Tables |
We've all learned to write programs a bit more generically than the immediate problem requires. We use interfaces in our code and include concrete implementation classes via some language-appropriate mechanism. We use factories to produce the object we want, rather than hard code them. We use code generators to spew forth mountains of code from configurable templates. Sometimes, we even generate SQL on-the-fly. It provides more flexibility that way; instead of having to write a separate query for every permutation of question, we can write something that can dynamically create the query, execute it and return the results.
At Initech, Ian was assigned an interesting JIRA ticket: Investigate errors regarding column length. Since that was all the information written in the ticket, Ian hunted down the author of the ticket to pry out a tad more information. Apparently, the part of Initech's intranet website that was used by the sales agents was suddenly throwing errors about some kind of maximum-size error, and he needed to find out what it was, why it was happening and how to fix it.
Sounds routine enough. Someone probably overflowed some buffer somewhere, or had too much data to fit in some column in the database.
The website in question was nothing out of the ordinary. It was written in PHP using the Zend framework connecting via PDO to a MySQL database. It had been mostly written by several programmers who had left the company a few months prior, and was of a quality that was not unusual for a corporate PHP website. There were functions with reasonably sensible names. The MVC pattern was applied in a rational way. It was possible to follow the code structure without retching or having seizures.
Of course, since this was a fairly decent sized company, there were also the requisite SQL injection vulnerabilities on every single input field. No input was ever sanitized; not even manually. There was no error checking on query result sets. Countless uninitialized variables littered the landscape, scattered amongst informative debug statements like: echo("whyyyyyyyy?");
The page producing the error was written by Gary. It was a multi-tabbed form with only some minor WTFs. One drop-down box had a completely different look&feel than all the others on the page, and any kind of error more complicated than a validation error produced the error message "1".
Sales agents were supposed to use it while talking to customers to enter information about the person they were calling. The error they were getting was a MySQL error regarding maximum row sizes, but it wasn't because of too much data in an input field. After a double-take and a quick Googling, Ian found that yes, MySQL -does- have a maximum size on the length of a row, namely 64KB. But this was just an Insert statement, right? What would maximum row length have to do with an existing table schema?
After several spelunking sessions down through the fetid bowels of the system, Ian found the fecal mass of detritus that was causing the problem.
It turns out that Gary was being micro-managed by the VP of Operations. This led to an endless series of requests to add a new field to the form. Gary got tired of doing the same work over and over, and took it upon himself to automate the problem. To this end, any time a new field was added to the form (usually by someone SSH'ing onto the remote server and just editing the necessary PHP files directly in production), the page would later on detect that the database did not have a matching column for it, and would create an alter table statement to add the new column to the database. Automatically. On the fly. With no human knowledge of, or intervention thereof. Live. In Production.
The fact that it had lasted several months without causing some kind of outage was impressive.
The name of the new column was the ID of the field on the form. But what would the data type be? The answer Gary settled upon was... varchar(255). Fast-forward a few months; all those varchar(255) columns started to add up, as management decreed more and more and more fields for more and more and more customer data to be recorded. While having a database table with 200+ Stringly-Typed columns is a WTF in and of itself, the fact that they were automatically added and with a substantial size only made the problem worse, particularly as 255 characters was far more than necessary for most fields. Two-letter state abbreviations, 5-digit Postal codes, 4-digit Zip+4 postal codes, 8-digit customer IDs, apartment numbers, phone numbers, and many others were all blanketed under the varchar(255) datatype.
While Ian wanted to tear out this monstrosity and banish it to the recesses of the Git commit log, he was informed by his boss that, since the Intranet website was going to be taken down in a few months, it would be more prudent to simply resize some of the columns to buy them enough time to take the whole site down. And so, choosing some of the more egregious offenders, Ian altered ten columns or so to reduce them to a sane size (or, better yet, to turn columns holding integer values into actual Integers).
Метки: Feature Articles |
Announcements: Free (New) TDWTF Mug Day - Time's Running Out |
There's only so much time left to get your free TDWTF mug, with the new logo and everything. Be the first kid on your block to have one.
Last year around this time, we did a Free T-Shirt Day. You all gave some great feedback, so I thought we'd try it again with a Free Mug Day!
My company, Inedo, will be once again sponsoring this round of The Daily WTF mugs. Although we haven't yet released our v5 of BuildMaster yet, we've made a lot of big improvements since last year, and thought this would be a good opportunity to show them off. The mugs will be the same, serious grade as always -- but this time, they'll feature the brand-new logo (unlike the one below).
To get one, all you have to do is download and install BuildMaster, run through this quick configuration, and then fill out the form with your address, etc. It's the same process as last time, but it's a much different (and much easier) exercise — it shouldn't take more than fifteen minutes or so.
Everything's free, and there's no credit card needed, or anything like that. This is just Inedo's way of thanking you for trying out BuildMaster. Afterwards, you can use the Express Edition for free, or upgrade to the Enterprise Edition.
This offer expires on March 29, 2015, and Supply is limited to 250, so sign up soon! To get started, just follow this link and, in a few weeks time, you'll not only be more knowledgeable about BuildMaster, but you'll be enjoying beverages much more fashionably with these nice, hefty The Daily WTF mugs.
http://thedailywtf.com/articles/free-new-tdwtf-mug-day-time-s-running-out
Метки: Announcements |
CodeSOD: Negative Creativity |
Pop quiz: how do you ensure that a number is negative? You could do something like:
if (count > 0) {
count = count * -1
}
Or you could use a ternary:
count = count > 0 ? count * -1 : count;
Or, if you're feeling fancy, use absolute value, like
count = Math.Abs(count) * -1;
If you're Justin's coworker, however, that's not good enough. No, what you REALLY want to do is coerce to a string, prepend a negative sign, then remove any double-negatives to make a positive again:
if (count > 0 || count < 0)
{
string tCountDelta = "-" + count;
tCountDelta = tCountDelta.Replace("--", "");
// Some time later...
int countDelta = int.Parse(tCountDelta);
}
Now that's fancy.
Метки: CodeSOD |
Error'd: Merry Christmss |
"I'm not sure what happened...maybe they ran out of vowels?" Mitch wrote.
"I know it's important to pay close attention to my portfolio, but I think SigFig could have just put 0% instead.," writes Dave
Scott K. writes, "Alright, I guess I'll take zero."
"While trying to install some debugging tools, I found that Asia simply won't allow it," writes Johnathan R.
"When this model wouldn't open, at first I'd tried looking in my shoes," Will R. wrote, "but now I know exactly where to start. Thank you Autodesk!"
Austin writes, "I got this message when opening a solution in Visual Studio 2010. I am assuming it means 'may not be available', but I don't know."
"Ummm...Seems like an assertion that should fail every time?" asks Dinesh M.
Jay C. writes, "Looks to me like someone the fact checker on this mobile app from a news organization launched by a peacock and a paper clip."
Метки: Error'd |
The Awesome Optimization |
Dave liked to think that he was a responsible, thorough application developer. He always tried to understand a problem before tackling it, to think through all ways a change could affect things, and to gather information before making decisions. So when he received complaints about the speed of the custom web application used by his work’s health department, he decided to do a little research to gather all the facts before reporting the issue to his boss.
And sure enough, all it took was a little research: the logs were full of database query timeouts and memory limit terminations. After a small amount of performance analysis on the test database server, it was very clear that the database was by far the main cause of the slow speeds. As the number of entries in the database naturally increased, many of the queries became exponentially slower.
Satisfied he had actionable information, Dave went to his boss to get approval to make fixes.
“Thank you, Dave! But the database isn’t your job - you’re an application developer. Anything related to the database is the DBA’s job. I’ll get ‘Awesome’ on this right away.”
‘Awesome’, the affectionately-nicknamed-by-the-boss local Database Administrator (DBA), had no experience programming, but was considered “master of all things even tangentially database-related”. Dave tried to make his boss aware of an important caveat: “But the data access code is in the application. How can the DBA optimize it there?”
His boss was resolute: “That. Is. Not. Your. Job. Don’t even worry about it. I’m sure Awesome knows how to do it.”
And so instead of optimizing queries, Dave begrudgingly set up another testing instance of the application for Awesome to work with and handed over the details. Three days later, Awesome showed up at his door with bad news: “The application is completely broken.”
Incredulous, Dave logged in to debug a little and quickly discovered that the “web.config” file had been modified and was pointing to an incorrect server. “Awesome, please do not modify any code or application settings without letting me know. Modifying the web.config file can be dangerous if you don’t know what you’re doing. Just optimize by profiling the database on the testing database server - you don’t need to dig through the code.” With a glare, Awesome left, never to be heard from again.
Until 5 days later, when he showed up at Dave’s door with amazing news: “It’s done.” Again incredulous, Dave logged into the test instance… and was shocked by how fast it was. Every page loaded nearly instantly. Even complex records searches displayed results immediately. Not a single perceptible delay remained.
“How did you do it?”, Dave asked.
Awesome was recalcitrant: “You don’t need to know. It’s not your job. All you need to know is that it’s a lot faster, and I did my job.”
Dave pressed him further. Had he modified any code? Had he added any indexes? What changes had he made?
“No, no changes in code, like you told me. The code is your job”, Awesome calmly informed Dave. Honestly puzzled, Dave pressed one more time for details: “Well… what exactly did you do?”
“Oh, the old database server was really slow, so I copied the database to a new server with a lot more RAM.”
“So copying the database to another server took 5 days?”, Dave asked.
“Well, I also had to archive some old records. The database had too much data in it.”
And that’s when Dave discovered the real reason things were so fast on the test instance: Awesome had “optimized” the database by simply removing a lot of data from it. Were it full of logs, or other data that had a defined shelf-life, this might have been acceptable. But as the database was full of the health department’s records that had to be maintained, this was pretty much the definition of Not Okay™.
“Awesome, we can’t just delete data from the database. We have to maintain those health records.”
At least the changes hadn’t been deployed to production.
“… But… I already made the switchover to the new database server.”
And that’s when Dave checked the production instance and realized that it, too, was similarly fast. And that it, too, was similarly missing lots of records.
As luck would have it though, Awesome was not very thorough at his job, and he hadn’t bothered to touch the old database on the original server. So Dave logged in, changed the configuration to point at the original location, and the site came back up with all old records intact… and without the “optimizations” that Awesome had put in place. He informed Awesome: “No worries - I’ve fixed it. All the data is back. Just leave the new server up for a bit so all the changes can sync. I’ll let you know when it’s done.”
As Awesome walked away, confused but relieved, Dave settled in for a long day’s work. Someone was going to have to manually merge any new entries and records changes back into the original database - and then actually improve performance. And, while it wasn’t his job, Dave figured that those tasks might be better left to someone a bit more understanding and thorough, instead of someone “awesome”.
Метки: Feature Articles |
CodeSOD: Waiting for File IO… |
Trisha had the misfortune to inherit some old Cold Fusion code. One particular block needed to see if a file existed before it continued, and apparently the original developer really wanted to be patient and make sure the file was there, so they wrote this:
Метки: CodeSOD |
The Lockdown |
2014 was waning, and Stacys team was struggling to deliver all the projects the director wanted before year-end. Insuracorp was a small, and that meant IT had a minuscule head-count. This meant they needed to bring on a Highly Paid Consultant for the last project, Codename: Lockport.
A manager had read a dire article about hackers dropping thumb drives in a parking lot, which their victims then picked up and plugged into their computers. This meant that it was now absolutely vital for the organization to ban all unapproved USB devices from being connected to the company systems. George, the HPC, was a hardware expert, so hed been running the show on Lockport while Stacy and her teammates cranked through the rest of the project list: upgrade mailservers here, replace a macro-laden Excel sheet with actual software there, discover that an Access database was suddenly critical to business operations, and the business wanted it ported to SharePoint. It had been a busy year, and Stacy was ignorant of Georges progress until her boss, Jeff, appeared in her cube one day.
Morning, Stace! Great work on that Exchange migration. I need a favor: George really could use a hand with Lockport. Im not sure what the issue is, but hes not making quite as much progress as wed like, and year-end is closing in on us. If you could give him a hand, thatd be great.
Stacy obliged, and took the elevator down to the basement room where George waited. His shiny bald spot was the only thing visible above the piles of USB devices teetering on every surface of his makeshift office.
George? Stacy was inclined to whisper, fearing the slightest reverberation would bury her co-worker alive.
Cant figure out… George said, trailing off into mumbled profanity. Stacy approached carefully, finding the round, red-faced man hunched over his laptop, popping the USB cable of a mouse into and out of each port in turn, as though performing a Zen ritual.
George? Its Stacy, from upstairs. Jeff asked me to come down and see if you needed a hand?
Not unless you can find a way to keep a USB device on the whitelist when its hardware ID changes every time!
That took Stacy aback. USB hardware IDs were burned into the device by the manufacturer, and she wasnt aware of any circumstances under which they could change. Then again, George was the expert. Maybe he was doing something unusual.
I didnt think that was possible. Can you show me?
Stacy peered over a stack of removable hard drives, careful not to send the pile tumbling to the floor. George was using an app called DevViewer to see the hardware IDs of the devices he was testing. The window showed a simple tree-view that organized all connected devices by category. He pointed to the mouse, named VID_081&PIT_1001
, under the Human Interface Devices category, and told Stacy to watch closely. He unplugged the mouse; its entry vanished from the list. After a five-count, he plugged it into a different port. He immediately selected the last device in the HID category, outlining its ID in a damning blue highlight: VID_0A81&PID_3016
.
SEE?! George said. Its that… that dam PID! How am I supposed to whitelist all of these in the Endpoint Protector whet the Port ID changes every time I plug them into a different port?
Stacy blinked rapidly, wondering if the dusty atmosphere of the basement had messed with her vision: she was quite sure there had been three devices in the HID section, and now there were only two.
Is the… Before Stacy could finish her thought, George yanked the mouse out of the second port and jammed it into a third.
And this time its the same! Its maddening!
Before George could pull the plug once more, Stacy reached over and clicked on the disclosure button for the Other Devices tree. There, plain as day, was VID_0A81&PID_1001
. Now, just give it a second, Stacy said. Sure enough, the mouses ID vanished from Other Devices moments later, only to reappear under HID.
When you first plug it in, Stacy said, it takes a few seconds to load the device drivers. Until it does, the device just registers as Other, and thats why it looks like the IDs are changing. Theyre just moving between the two lists.
George sat back, eying the devices heaped around him. He looked everywhere but towards Stacy. Shed just shown, with a simple observation, that the past few weeks of struggle against capricious device IDs had been pointless.
Stacy tried to fill the silence. I guess thats why a second pair of eyes is always useful, huh? A twitch in his left eyebrow was Georges only response.
Though he never spoke to Stacy directly, George managed to communicate through Jeff that her input was no longer required. She figured he hadnt liked being shown up, and was more than happy not to visit the basement again. Stacy returned to her project list and forgot about Codename: Lockport.
The year wound down, and on New Years Even, Insuracorps virtual server environment ground to a complete and total halt. Access Denied and Unexpected Error dialogs graced the screens of every workstation, and Jeff scrambled the IT squad to investigate.
Stacy, look at this, Steve said, pointing to the dashboard of the database server he administered. The system disk is here, but it says all the other drives, including the data drives, are unmounted! Could this have to do with Codename: Hot Potato?
Stacy scanned the list of red-lit, unmounted drives, her teeth clenched. Hot Potato was a virtualization project she and a few virtualization specialists had wrapped up. Its purpose was to reconfigure several dozen VMs so they could hot-add CPU and RAM. That mode was all-or-nothing: the VM disks became hot-addable as well, causing them to be treated as removable storage.
Removable storage, Stacy muttered to herself.
Huh? Steve said.
… like they were USB drives. Jeff! Stacy yelled across the cube farm, prompting her boss to jog over.
Whats up? Figured it out?
That depends. Whats the latest status on Codename: Lockport?
Hmm… Jeff consulted a spreadsheet, awkwardly loaded and displayed on his omnipresent BlackBerry. Right. Since the Endpoint Protection config never panned out, George decided to block all USB drives via group policy. Looked good on his test machines, so he rolled it into Production… Jeff looked up, chewing his lip, this morning.
Stacy made an unhappy sound that rhymed with duck. Steve looked between the two, knowing only that whatever was going on wasnt good. As a junior database admin, he hadnt been privy to either Hot Potato or Lockport. Guys? He asked, What are we going to do?
Were going to revoke that group policy, Stacy said. Then the VMs wont be banned from accessing their own storage, and then we can have George give Endpoint Protection another go.
Forget it, Jeff said. Its a new year, and I think its time for a new hardware expert.
Метки: Feature Articles |
Coded Smorgasbord: Dating Woes |
As we all know- especially those of us who just "sprung ahead" this weekend with Daylight Saving Time- dates, times, and time zones are complicated beasts. Handling them programmatically is even harder. Computerphile put together a great video on this topic, which is worth watching to understand why we receive so many Error’d submissions regarding downloads that claim they won’t finish until after the heat death of the universe.
Here are some examples of mind-bending code attempting to wrangle with an already mind-bending topic...
First up, Tom discovered this date formatting gem in an inherited application, in the Page_Load of several pages:
// To display the date in the UK fromat.
string[] Months ={ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
int Day, Month, Year;
string dt = DateTime.Today.ToShortDateString();
string dt = DateTime.Today.ToString("MM/dd/yyyy");
string[] temp = dt.Split('/');
string date = null;
Month = int.Parse(temp[0]) - 1;
Day = int.Parse(temp[1]);
Year = int.Parse(temp[2]);
date = Day + "-" + Months[Month] + "-" + Year;
Next, this highly questionable conditional Andrew found in his product- three times. Maybe next time, someone should just spend ten seconds Googling what DateTime.MaxValue is...
if (date.Date == new DateTime(9999, 12, 31))
{
date.Date = DateTime.MaxValue;
}
Brian found a lovely business day function in PHP that had been committed with the message, "fix for memorial day 2012:"
private function isBusinessDay( DateTime $date ) {
$dateStr = $date->format('Y-m-d');
$dayOfWeek = (int) $date->format('w');
return !( $dayOfWeek === 0 || $dayOfWeek === 6 || $dateStr == "2012-05-28" );
}
An Anonymous friend writes: "As a teaching assistant on a course on software architecture I frequently encounter code which makes me cringe. However, I've rarely seen such a commitment to statically typed languages before..."
public void Remove(Calendar calendar)
{
// Preconditions
Calendar c = new Calendar();
if (c.GetType() != calendar.GetType())
{
throw new InvalidOperationException("calendar param has wrong type.");
}
...
}
Finally, a delightful Perl sample from Jim N. "One of the other programmers here is particularly fond of 'clever' Perl. This kind of date string generation exists throughout our application. There's lots of other areas of code that could be replaced with old, stable CPAN libraries, but... nope. This whole slug of WTFery can be replaced with: DateTime->now()->strfmtime("%Y_%m_%d_%H%M");
"
sub get_timestamp
{
my $year = (localtime)[5] + 1900;
my $month = (localtime)[4] + 1;
if ( $month =~ /^\d{1}$/ )
{
$month = '0' . $month;
}
my $day = (localtime)[3];
if ( $day =~ /^\d{1}$/ )
{
$day = '0' . $day;
}
my $hour = (localtime)[2];
if ( $hour =~ /^\d{1}$/ )
{
$hour = '0' . $hour;
}
my $min = (localtime)[1];
if ( $min =~ /^\d{1}$/ )
{
$min = '0' . $min;
}
my $sec = (localtime)[0];
if ( $sec =~ /^\d{1}$/ )
{
$sec = '0' . $sec;
}
my $res = $year . '_' . $month . '_' . $day . '_' . $hour . $min;
return $res;
}
Метки: Coded Smorgasbord |
Error'd: Spoiler Alert |
"The following image contains spoiler information. Due to the fact the material in this image will spoil upcoming errors, we have removed the excerpt so you must click the image to view the image contents," writes Jay M.
Mitch wrote, "Optional? If you leave the name blank, you get an internal error and a phone number for support."
"I'm glad that BBC News' readers are as concerned about 'Unnamed page'," writes James W.
"While fixing my parents' computer, I discovered that they had taken up photography...in a big way," writes John.
"Noticed this on my bank's home page. Clearly their credit card has something out of the ordinary," Nick B. wrote.
Lasse Y. writes, "Here are a lot of cards.... or something to make up for lack of card, at least according to Skype."
"I'm trying to download System Center 2012, but why does MS keep on insisting that I should get SQL Server instead?" asks Nikolai.
"I just upgraded to Windows 8.1 and needed to uninstall all Comodo software by hand in order to upgrade it," Jaroslaw F. writes, "Sadly, seems I still need Windows 8 to uninstall this tidbit."
Метки: Error'd |
Spared No Expense |
Renees company was a Silicon Valley managed services company. They needed the best data-center they could find to house their infrastructure, and cost was not an object. They loaded up a dump truck full of money and went shopping for the most expensive hosting they could find.
For Renee, this meant lots of data-center tours. She played the tame geek for her management, ostensibly there to inspect the IT services. Her bosses were just there to see how much their prospective vendors would butter them up to close the deal.
The front-runner was a company called Isla Nublar. Their first experience on the tour was a massive security gate, guarded by two armed men and a dog. They gave the entire car a quick search, including using mirrors to inspect the undercarriage. After being sniffed over by the dog and having their ID checked and re-checked, Renee and her bosses were allowed through.
The building itself came from the an alien spaceship has landed school of architecture. It was steel, glass, organic curves and confusing arcs. A security guard and a sales engineer named John greeted them at the door. Were so excited to have you here, John said. As youll see, weve spared no expense.
He showed them into a glass-walled atrium, full of natural light, tropical plants, and a catered spread laid out on a table, complete with coffee, macarons, and a sushi chef making rolls to order. Can I interest you in any refreshments? The coffee is Kona- weve spared no expense.
John showed them down the hall to the NOC. Behind the glass wall, staff bustled about the room, mostly ignoring the Mission Control-style wall display, and focusing instead on their own screens. Everyone looked busy, but didnt actually seem to be doing anything. It reminded Renee of animatronic figures in Disneylands old Mission to Mars ride, and they seemed about as useful.
As you can see, weve spared no expense. Now, let me get you ready to see the data-center floor.
Getting ready meant filling out piles of paperwork and NDAs, collecting everyones fingerprints, mugshots, and patting down everyone to ensure they werent smuggling a cellphone camera into the data-center.
The entry to the data-center floor was through a man-trap, the security version of an air-lock. One at a time, they passed through the outer door, and an armed security guard waited for it to seal before pushing the button that released the inner door. After everyone cycled through, John reminded them, Weve spared no expense.
Over the noise from the racks, John shouted out the key features. The floor was raised, and each tile had a dedicated sensor to detect if it were moved. There were motion sensors, water sensors, and a few times, John mentioned laser beams. Every millimeter of the space was watched by cameras, and the room itself was a Faraday cage. The supports were earthquake proof and the walls were lined with Kevlar. They had triply redundant backup generators, and each rack had dual, independent power legs, in case anything went wrong with one of them. Each rack was secured with a grille that could only be opened with an admins ID badge.
As you can see, John began.
Youve spared no expense, Renee finished. I get it.
Duly impressed, management signed the contracts the next day. That weekend, Renee and her team had to move their hardware in through the secure loading dock, which was just a regular loading dock with a sign that said, Secure Area. None of the extremely paranoid security they had seen coming in the front way was in sight here. No one complained, because it certainly made moving in easier.
By Saturday night, everything was up and running. The switchover went without a hitch, and the customers hadnt noticed a thing.
By Sunday morning, disaster happened. Machines were down, network was down, and the customers were enraged. Renee was on the phone with the data-center support in an instant, and before five minutes had passed, John joined the call, trying to smooth things over. I just want you to know, weve got no other outages. Weve got the best electricians in the business looking at what appears to be a power outage in one of your racks. Weve spared no expense.
The first challenge for the electricians was simply getting permission to lift floor tiles without setting off every alarm in the building. They traced the power lines, but found no fault between the mains and the rack, which meant the problem must be in the rack itself.
Theyre trying to trace the fault in the rack, but they cant access the power cabling, John explained.
What?
Well, we spared no expense. Our racks are custom built. The power lines run inside the frame of the cabinet. Im getting Ray, one of the admins to join the call from the floor.
This is tricky stuff, Ray said, and I dont know how quickly we can fix this.
We need our servers up now, Renee said.
Right, so heres what I can do- I can move your servers to one of our empty cabinets. Sound good?
Whatever it takes.
We have spare cabinets, John said, because we spared-
Just get our servers back up.
Ray stayed on the line while he worked. Renee heard him slide a server out of the cabinet and then say, Hunh, thats interesting.
Thats not something I want to hear when youre moving my servers.
Theres a strange black switch down here. Ive not seen a black switch in any of the other cabinets.
Ray checked one of the other cabinets, and sure enough, it had a bright glowing red switch. Hold onto your butts… Ray said. He flicked the black switch in Renees failing cabinet. The light turned red, and the servers spun right back up.
The switch was inconveniently placed, near the floor, where someone passing by the cabinet could accidentally jostle it, which is likely what happened. Unfortunately, moving the switch wasnt possible. With their bizarre internal power cabling, and the way the switch was soldered to the internal power strip, it would require cutting, drilling, and probably a bit of welding to move it.
The only practical fix was to use tape to secure the switch in the on position. Well use the best tape money can buy, John said, and it wont come off. Well spare no expense!
Метки: Feature Articles |
CodeSOD: SearchGuard |
In a professional situation, an incorrectly selected record can result in a mortifying loss of data. Therefore, it behooves one to select the proper row carefully in one's stored procedure. That's why Charles's development team uses SearchGuard, the premier design pattern for selecting just the right row:
DELETE FROM [dbo].[tbl_employee] WHERE ((
[employee_id] = @Original_employee_id)
AND ([salesperson_flag] = @Original_salesperson_flag)
AND ([first_name] = @Original_first_name)
AND ([last_name] = @Original_last_name)
AND ((@IsNull_job_title_type_id = 1
AND [job_title_type_id] IS NULL) OR ([job_title_type_id] = @Original_job_title_type_id))
AND ((@IsNull_address_id = 1 AND [address_id] IS NULL) OR ([address_id] = @Original_address_id))
AND ((@IsNull_work_extension = 1 AND [work_extension] IS NULL) OR ([work_extension] = @Original_work_extension))
AND ((@IsNull_home_phone_number = 1 AND [home_phone_number] IS NULL) OR ([home_phone_number] = @Original_home_phone_number))
AND ((@IsNull_alternate_phone_number = 1 AND [alternate_phone_number] IS NULL) OR ([alternate_phone_number] = @Original_alternate_phone_number))
AND ((@IsNull_relative_name = 1 AND [relative_name] IS NULL) OR ([relative_name] = @Original_relative_name))
AND ((@IsNull_relative_phone_number = 1 AND [relative_phone_number] IS NULL) OR ([relative_phone_number] = @Original_relative_phone_number))
AND ((@IsNull_hire_date = 1 AND [hire_date] IS NULL) OR ([hire_date] = @Original_hire_date))
AND ((@IsNull_termination_date = 1 AND [termination_date] IS NULL) OR ([termination_date] = @Original_termination_date))
AND ((@IsNull_team_type_id = 1 AND [team_type_id] IS NULL) OR ([team_type_id] = @Original_team_type_id))
AND ((@IsNull_comment = 1 AND [comment] IS NULL) OR ([comment] = @Original_comment))
AND ((@IsNull_social_security_number = 1 AND [social_security_number] IS NULL) OR ([social_security_number] = @Original_social_security_number))
AND ((@IsNull_drivers_license_number = 1 AND [drivers_license_number] IS NULL) OR ([drivers_license_number] = @Original_drivers_license_number))
AND ((@IsNull_badge_number = 1 AND [badge_number] IS NULL) OR ([badge_number] = @Original_badge_number))
AND ((@IsNull_hourly_wages = 1 AND [hourly_wages] IS NULL) OR ([hourly_wages] = @Original_hourly_wages))
AND ((@IsNull_w2_claim = 1 AND [w2_claim] IS NULL) OR ([w2_claim] = @Original_w2_claim))
AND ((@IsNull_insurance_start_date = 1 AND [insurance_start_date] IS NULL) OR ([insurance_start_date] = @Original_insurance_start_date))
AND ((@IsNull_date_of_birth = 1 AND [date_of_birth] IS NULL) OR ([date_of_birth] = @Original_date_of_birth))
AND ((@IsNull_shirt_size_type_id = 1 AND [shirt_size_type_id] IS NULL) OR ([shirt_size_type_id] = @Original_shirt_size_type_id))
AND ([active_flag] = @Original_active_flag) AND ([network_userid] = @Original_network_userid)
AND ((@IsNull_vacation_days = 1 AND [vacation_days] IS NULL) OR ([vacation_days] = @Original_vacation_days))
AND ((@IsNull_sick_days = 1 AND [sick_days] IS NULL) OR ([sick_days] = @Original_sick_days))
AND ((@IsNull_last_vacation_update = 1 AND [last_vacation_update] IS NULL) OR ([last_vacation_update] = @Original_last_vacation_update))
AND ([part_time_flag] = @Original_part_time_flag)
AND ((@IsNull_part_time_hours = 1 AND [part_time_hours] IS NULL) OR ([part_time_hours] = @Original_part_time_hours))
AND ([first_eligible_bonus_received] = @Original_first_eligible_bonus_received) AND ((@IsNull_first_eligible_bonus_received_date = 1 AND [first_eligible_bonus_received_date] IS NULL) OR ([first_eligible_bonus_received_date] = @Original_first_eligible_bonus_received_date))
AND ([awa_location_id] = @Original_awa_location_id)
AND ([rowguid] = @Original_rowguid)
AND ((@IsNull_bonus_view_date = 1 AND [bonus_view_date] IS NULL) OR ([bonus_view_date] = @Original_bonus_view_date))
AND ((@IsNull_ceiva_flag = 1 AND [ceiva_flag] IS NULL) OR ([ceiva_flag] = @Original_ceiva_flag))
AND ([ethnicity_id] = @Original_ethnicity_id)
AND ((@IsNull_sex = 1 AND [sex] IS NULL) OR ([sex] = @Original_sex)))
Its powerful protection reduces the risk of false positives to practically zero, and with a plethora of fields to match on, it's virtually impossible to delete the wrong row.
SearchGuard: Anything less would be uncivilized.
Метки: CodeSOD |
Codename: Cloudy Viper |
In the interview, Initech seemed nice enough. The managers seemed like nice, normal people, and the companys vibe seemed quite good. When Terrence was extended an offer, he accepted and joined.
Things immediately went south. A major client cancelled after years of mounting frustration with Initechs software. A major client, and that affected cashflow enough that Initech was forced to downsize.
The hatchet-job on the staff moved a developer named Boris up to the Lead Architect position. Boris was a weird bloke with odd social skills and a big, greasy lollipop head, but the staff whispered in awe of his legendary programming skills. As one co-worker explained to Terrance, Boris knows everything there is to know about software engineering techniques, he just doesnt bother to use them. By skipping over trivial steps, like requirements gathering, documentation, and testing, Boris was able to develop new applications very quickly, and that speed was important if Initech was going to start getting clients again.
Boris took the lead on a new project, code-named Cloudy Viper. The name was apt, because without any formal requirements or development plan, its intended purpose was quite murky, and it poisoned any developer not named Boris. Turnover hit 60% that year, as Boris burned through the development team, churning out terrible, mostly incomprehensible, and untested (and untestable) code. Its important we get core feature working, he explained before passing the code off to junior developers to make production-worthy.
Over time, the product oozed out and was released to multiple clients, for utterly different purposes. A modular or plugin-based architecture would have been perfect, but instead the big ball of mud was given to all of the customers, with no variation. This meant customers who bought a system to manage their ice cream inventory also had tools to herd cats. The user interface was so hacked together and hostile, some screens required users to manually enter their own SQL into a text box.
As Cloudy Viper poisoned developer after developer, it was only a matter of time before Terrance was exposed to the project. Boris handed him thousands of lines of scripts and includes, some with millions of lines of code, strewn like electronic garbage around a senseless directory system, and a single exception handler in the top-level Main
function, which handled all exceptions for the application and would eventually crash the Visual Studio debugger.
One line stuck out to Terrance:
thechkbox = currRating[0].parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.children(2).children(0).children(0)
thechkbox.disabled = false;
The database backend was a classic example of the Inner-Platform Effect, containing tables of tables and tables of fields and tables of datatypes. Terrance began interviewing with other companies, and along the way, met several other people who used to work at Initech.
They all asked the same thing: Does Boris still work there?
Hes the Lead Architect now.
I can see why youre leaving.
Метки: Feature Articles |
CodeSOD: Polish Elections |
Far away across the Atlantic, in the mythical land of Eastern Europe, where the sun don't shine and wild beasts roam the roads, lies a little country called Poland. Known in the world for its cheap manual labor and fondness for strong alcohol, it has for years been the butt of every national joke in almost all parts of the globe. But people here (or at least those who haven't run away yet) have been working hard to combat those pesky Eastern Bloc stereotypes, and as such, the country has in recent years seen a lot of social and technological progress. That last one, of course, comes with one notable exception: the government sector.
Obviously, most countries' governments have a love-hate relationship with technology- but the Polish government invariably tends to be special. Between national-level exams being leaked by putting them in an unprotected folder with directory listing turned on, and the Social Insurance department buying 130,000 floppy disks in the year 2008, our government's technological proficiency has us ranking slightly below Elbonia. And so, when it was announced that the next local elections would be far more computerized than any of the previous ones, everyone trembled in fear.
The election day came and passed. At that point, everything was still done using pen and paper, so nothing had a chance to break. But soon after, the Polish Electoral Commission announced that the election results might be "slightly delayed". At the same time, someone in one of the local commissions with access to the software used in vote processing noticed an odd .pdb file with debugger symbols in the program folder. Being a good citizen, they immediately took a decompiler, restored the source code in full, and put it on GitHub for everyone to see.
Now, the following part might not be for the faint of heart. Here's one of the most notable source files from that GitHub repository.
This particular piece of code had one simple task: taking XML files with election results and generating an HTML file with an official election protocol. There are many ways to approach that task. The more clever people would probably go for an XSL transformation. The slightly less clever ones would use an HTML template and fill it with data. This code, however, does not try to be clever. It aims to keep things simple, using an old and trusted way to achieve its goal:
this.header = "”;
And it’s all downhill from there. Down a very rocky hill, full of cliffs and jagged edges, whose exact shape can be seen by scrolling down the GitHub page. After just a bit of introductory code comes the getProtocol
method- a massive, 2000-line behemoth full of foreach
es, if
s, and else
s iterating over the XML document and nested so deeply that some lines simply fail to fit on the screen.
Other WTFs include, but aren’t limited to:
On Error Resume Next
in the form of catch (System.Exception) {}
response += "
”;
StringBuilder
s to be too 2000’s and using good old performance-murdering string concatenationAfter that leak, the news a few days later that the results will be delayed even further came as no surprise to anyone even remotely tech-savvy. Oh, and the part of the code that failed? The protocol printing module, a.k.a. today’s Exhibit A.
Метки: CodeSOD |
Error'd: An Odd Form Factor |
"I was searching on Texas Instruments' web site when I found a block diagram for an oddly-shaped tablet," writes Renan B., "I mean, Gigabit Ethernet? PCI Express? I had no idea that they could squeeze in all these features!"
Jason wrote, "I knew the Doctor was a time traveler, but it took Hulu to inform me that episodes of Doctor Who came from the future."
"I wonder if this is Comcast's way of telling me that my Internet is really, really slow," writes Kurtis.
"Adding a password is a good idea, but I'm not sure about this site's implementation," writes Mike.
"Thanks for the help, Mathematica! I know exactly what I need to fix now!" Michael E. wrote.
Jeff T. writes, "While trying to purchase a replacement filter for my fridge from my phone, I encountered this fun math at Amazon."
"Well...like it or not...looks like I'm getting email updates," Dan V. wrote.
Ben A. writes "On the bright side, after I took this screen-shot, the computer proceeded to run for the next hour with the little exclamation mark on the battery icon".
Метки: Error'd |
Consultant Designed Success |
Circa 2005, using XML and XSLT to generate HTML was all the rage. It was cool. It was the future. Anyone who was anyone was using it to accomplish all-things-web. If you were using it, you were among the elite. You were automatically worth hiring for any programming-related task.
Back then, Richard was working at a small web development company. In this case, "small" means the boss, whoe was a bright guy, but who had absolutely no knowledge of anything -web, -computer or -technology related would make all decisions relating to hiring, purchasing technology and creating technology procedures.
Although Richard was trained as a developer, he had been doing some integration work on small client web sites while the company pursued bigger goals of developing a web portal framework that would allow them to pump out dozens of web portals. To help with the overall architecture, the boss hired an Architect who specialized in intelligent transactional agents. One of his claims to fame was a system he had previously built to map data to presentation HTML via XML and XSLT. The boss was impressed by his understanding and use of these technologies, and based almost entirely on just that, hired him.
The architect spent several months analyzing the underlying data and all the state transitions that would be required, as well as the target HTML into which it had to be morphed. Then he spent several more months coding up the framework. One of the key pillars on which this framework was built was the extensive use of XML and XSLT to convert all the data into something a browser could interpret to render.
When the consultant began to integrate his work with the rest of the infrastructure, lots of little problems started to pop up. For example, source control was really just copying the source tree to a dedicated directory on one developer's laptop. When the consultant had to deploy his latest jar, he would copy it to a network share, from which the developers would copy it locally to use it. However, at some point, the moving of the jar file became significantly less important than the using of the contents of the jar file, and the bug reports began to pile up.
This particular application was basically a corporate directory categorized by region, commerce-type and category/sub-category/actual-category. There were 13 regions with about 4000 businesses, 4 commerce-types and about 300 categories. Any experienced developer would expect that searching for a specific business in region A, type B and category C would be quite fast. It would be reasonable to expect the query to complete in far less than one second. In practice, when all criteria were used, the web server timed out most search queries at 30 seconds.
Apparently, the consultant decided that every little thing should be its own class. No matter how small. A data object containing a Date was insufficient. No, there were separate objects to hold day, month and year, all of which were wrapped in a MyDate object. Ditto for time. Ditto for day of week. Ditto for everything else you could imagine. Then, to really test the capabilities of the IO subsystem, network and silicon, he would query every record in the entire database, construct objects for every component, sub-component, sub-sub-component, and so forth via Hibernate, and scan the list using the slowest possible mechanism in the Java language: instanceof, to see if an object was of a particular type before attempting to use it for purposes of comparison. To make matters worse, it repeated this entire process three times for each query; once to check if each business was of the proper instance for the region, once for the commerce-type and once more for the category.
Richard replaced the whole thing with a simple stored procedure that ran in less than 100ms.
Having dealt with that, Richard and peers told their boss what they went through and asked him to fire the consultant. He agreed, but only after the consultant would modify his framework to support multiple portals on the same system.
After two weeks, the consultant proudly proclaimed that the system now supported as many portals as they wanted. The procedure to enable this capability was to copy the entire project and rename it for each additional web portal.
Having ripped out all of that framework, they never even got to try out the part of the framework that morphed data into XML to be XSLT'd into HTML.
In the end, everything that the consultant did was trashed and rewritten by Richard and his peers in about a month.
Upon reflection, Richard learned that just because you have knowledge of how to use one tool doesn't mean that you are an expert in everything. He also learned that an otherwise intelligent boss can make really stupid decisions if he doesn't have the requisite experience in the relevant field.
Метки: Feature Articles |
CodeSOD: The Address Shuffle |
The best thing about being a consultant, in Ashleigh's opinion, was that you got to leave at the end of a job- meaning you never had to live with the mistakes your pointy-haired supervisor forced on you.
This client, an online retailer, just needed an update to their Web.release.config file to resolve their session-management issue. Ashleigh had been hired for a two-week contract, and on Wednesday of week two, the fix went live. Of course, she wouldn't get paid if she didn't manage to look busy, so Thursday morning, she was scrambling for a quick fix to add to the pile.
That's when Betsy, the manager, popped by the temp cube. "Hey, I just got some new code from the offshore team. Mind taking a look at it?"
Normally, Ashleigh would decline such a dubious honor; today, however, it seemed easier than digging at the growing pile of minor defects, so she agreed. The method in question was meant to eliminate blank lines in the middle of the address on an invoice, because it "looked weird" to the accounting department.
Sure, whatever, Ashleigh thought. Dubious cost-savings were hardly unusual in a company that offshored their main development team and paid Ashleigh's exorbitant fees to clean up after them.
private string FormatAddress(Address address)
{
if (address.Line1 == null or address.Line1 == "")
{
address.Line1 = address.Line2;
address.Line2 = address.Line3;
address.Line3 = address.City;
address.City = address.PostalCode;
address.PostalCode = address.Country;
address.Country = null;
}
if (address.Line2 == null or address.Line2 == "")
{
address.Line2 = address.Line3;
address.Line3 = address.City;
address.City = address.PostalCode;
address.PostalCode = address.Country;
address.Country = null;
}
if (address.Line3 == null or address.Line3 == "")
{
address.Line3 = address.City;
address.City = address.PostalCode;
address.PostalCode = address.Country;
address.Country = null;
}
if (address.City == null or address.City == "")
{
address.City = address.PostalCode;
address.PostalCode = address.Country;
address.Country = null;
}
if (address.PostalCode == null or address.PostalCode == "")
{
address.PostalCode = address.Country;
address.Country = null;
}
return address.Line1 + "
" +
address.Line2 + "
" +
address.Line3 + "
" +
address.City + "
" +
address.PostalCode + "
" +
address.Country;
}
The best part, Ashleigh mused as she skimmed over the code for a third time, is that it fails miserably at its goal. It always returns the same number of lines. And if both lines 2 and 3 are empty- probably the majority case- it still leaves a gap in between.
A moment's browsing of the rest of the codebase revealed an even better part: it modified the fields on the address, leading to odd validation bugs later on when the city (which might contain the postcode now, or even the country) or postcode were used.
"My recommendation?" Ashleigh typed into an email she knew she wouldn't send. "Fire the offshore team altogether. Or at least stop paying them by the line."
Метки: CodeSOD |
Announcements: Free (New) TDWTF Mug Day! |
Last year around this time, we did a Free T-Shirt Day. You all gave some great feedback, so I thought we'd try it again with a Free Mug Day!
My company, Inedo, will be once again sponsoring this round of The Daily WTF mugs. Although we haven't yet released our v5 of BuildMaster yet, we've made a lot of big improvements since last year, and thought this would be a good opportunity to show them off. The mugs will be the same, serious grade as always -- but this time, they'll feature the brand-new logo (unlike the one below).
To get one, all you have to do is download and install BuildMaster, run through this quick configuration, and then fill out the form with your address, etc. It's the same process as last time, but it's a much different (and much easier) exercise — it shouldn't take more than fifteen minutes or so.
Everything's free, and there's no credit card needed, or anything like that. This is just Inedo's way of thanking you for trying out BuildMaster. Afterwards, you can use the Express Edition for free, or upgrade to the Enterprise Edition.
This offer expires on March 29, 2015, and Supply is limited to 250, so sign up soon! To get started, just follow this link and, in a few weeks time, you'll not only be more knowledgeable about BuildMaster, but you'll be enjoying beverages much more fashionably with these nice, hefty The Daily WTF mugs.
Метки: Announcements |
Tales from the Interview: Limit as Sense Approaches Zeno |
Its an uncomfortable truth in our enlightened, 21st-century utopia, but we often dont know how to deal with people that deviate slightly from the norm. Jim knows a thing or two (or three) about this, because he has a Bachelors of Science with three majors: Computer Science, English, and Mathematics. Lets not dwell on how such a thing could be possible; consider instead the strangest reaction Jim ever encountered to his unusual credentials.
The developer position at Competitive Telecom Systems seemed straightforward, and a good fit for Jims skills and experience. When Jims interview time had arrived, a man found him in the reception area and shook his hand.
You must be Jim. Im Ted. Were very excited to have you here today!
Ted led Jim through a maze of beige corridors to a nondescript conference room and took a seat across from one of his associates.
This is Fred, Ted said, indicating the man across from him. He then nodded towards the third man, sitting between the two at the end of the table directly across from Jim. And this is Crispin. We asked him to join us especially to meet you.
Thats right, Fred said, he came as a favour.
Jim greeted Crispin, who said nothing, never raising his eyes from the document he was reading.
Ted began the interview with a simple programming question that Jim correctly identified as a string-reversal variant before describing an effective solution. Ted nodded, but paused for a moment before asking,
So, what, did you take a few CS and English electives as part of your Math degree?
Well, no, Jim said. My school offered a triple-major track, and I took it. Ive fulfilled the requirements for all three of my majors.
Of course, of course, Fred said, taking the reigns from his colleague, we just want to get an idea of where your focus lies. Would you say you consider yourself more of an Arts major that dabbles on the Science side of things, or the other way around?
I suppose if I had to choose, I am applying for a developer role. So I see myself as a Computer Scientist first and foremost, Jim furrowed his brow, trying to determine what his interlocutors wanted to hear. Were they afraid he didnt have what it took to be a developer? That the variety of subjects hed studied meant he couldnt commit to a given task? The conversation went back to typical questions, Ted alternating with Fred, each of them unable to resist circling back to Jims unusual degree. All the while, Crispin remained absorbed in the document. He turned it over and over, as though trying to memorize the words on each side of the single sheet that Jim eventually recognized as his r'esum'e. When Fred and Ted had run out of steam, and Crispin still seemed unaware that a candidate sat across the table from him, Jim leaned forward and asked if they had any other questions for him.
Ted and Fred turned to their grim colleague, the one whose presence in Jims interview had been specially requested. Crispin let Jims r'esum'e flutter to the desk, raised his head, narrowed his cold, grey eyes.
I have a question, Jim. A Math major would know about integration and differentiation, right?
Of course, Jim nodded. Basic calculus&
Yes. And a Computer Science major would have encountered the concepts of black-box and white-box testing?
Yes, black-box is where you test the external interfaces of a given module without assuming knowledge of its internals, while white-box—
Good. And, as an English major, you must have spent a lot of time drawing comparisons between works?
I did, yes& Jim leaned forward, peering at Crispin, unsure what these questions were building to.
Okay Jim, Fred said, Now, listen closely.
This is why Crispin came today, Ted added.
Crispin cleared his throat and glared at his lackeys. Heres what I need you to do, Jim, he said. "I want you to compare the concepts of integration and differentiation with those of white- and black-box testing.
In your own words, of course.
Jim gaped. Ted and Fred sat back, arms crossed, expressions indicating their satisfaction.
Crispin spent two days with your r'esum'e, just to come up with that question, Ted said.
Thats right; no one comes up with questions as challenging as Crispins, Fred said. When we saw your education history, we knew we had to call him in.
Yes, yes, Crispin waved them aside, thats fine. Well, Jim? What do you and your three majors have to say for yourselves?
Jim racked his brain, trying to conjure anything that could relate seemingly arbitrary concepts from different disciplines to one another. He was on the brink of muttering& inverse something, when reason asserted itself. He politely explained that he saw no way to compare those particular concepts. Glowering, the triad informed him that they had no further questions, and they would let him know their decision. The attentive reader of this publication will not be surprised to learn that Jim failed to get the job, and, though his career has since taken him elsewhere, he is still considering a new course of study to determine, with academic rigour, what an acceptable answer to Crispins masterstroke might have been.
http://thedailywtf.com/articles/limit-as-sense-approaches-zeno
Метки: Tales from the Interview |
CodeSOD: A Small Closing |
Dario got a call that simply said, Things are broken. When he tried to get more details, it was difficult for the users to pin it down more clearly. Things would work, then they wouldnt. The application would run, then it would hang, then it would suddenly start working again.
He knew that his co-worker, Bob, had been doing some performance tuning, so that was probably the right place to look. Bob, have you made any changes that might cause weird behavior?
No, no. Ive just been optimizing the file-handles.
Are you just using jargon to sound like you know what youre talking about?
No! I mean, Ive just been optimizing how we manage our file-handles so that we dont leave them open.
Oh, that makes sense. Show me. .
Proud of his clever solution, Bob showed him:
def close_all_files():
for fd in range(resource.getrlimit(resource.RLIMIT_NOFILE)[1]):
try:
os.close(fd)
except OSError:
pass
The function resource.getrlimit()
returns some resource limit that controls the behavior of the Python runtime. This could be the size of the call stack, how much CPU time its allowed to use, or in this case, the RLIMIT_NOFILE- the number of allowed file descriptors for the current process.
On a typical system, this number could be quite large. For example, 9,223,372,036,854,775,807. Then, for each one of those integers, the code then asks the operating system to pretty-please close any files with that file descriptor. If anything goes wrong, catch the exception and ignore it.
Now, the good news is that this cant close any files that werent currently opened by the Python process. The bad news is that it can close any file opened by the Python process. This triggered a cascading series of Bad file descriptor
errors, and every time the function ran, it would grind the system to a halt while it tried to close every possible file ever opened.
Метки: CodeSOD |