- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
He was registered before on the forums, as you can tell from his post count. "Oliver Klozov" is the name he used to submit his WTF to Alex.
I thought that was obvious.
Admin
Semaphores my butt. This is why you don't get/set mutable state willy-nilly when in fact parameters should be, well PARAMETERS to the actual encryption function.
The WTF is that soon-to-be-programmers are still told that OO is all about setters, getters and inheritance and that OO is a Good Thing. Wrong on both accounts, as we see from this WTF and from that comment.
Now excuse me while I barf in the W3C's general direction.
Admin
I bet the 'earlier piece of code' was actually:
return (pSomeObject = NULL)?FALSE:pSomeObject->TestSomething();
Admin
Some people think it's obvious.
Many, many people don't get it right away (esp. with Klozoff instead of Klozov).
Which is why I picked it :-)
Admin
Single-instance testing is a frequent vice ... failure to build or buy an infrastrucutre for realistic simulation.
Admin
That was also used as one of Bart's phone prank names in The Simpsons - I just assumed that everyone got it.
First.
Admin
And for those who constantly berate VB and the like, even VB6 soap servers had automatic state maintance. What language was this web service written in?
That great thing called java?
Wouldn't line the dogs basket with it....
Admin
Somebody sums up a lot of the design problems well.
I will just add that a distributed architecture is inherently multithreaded. So when you think of a distributed system, you immediately think of what race conditions can occur and design to avoid it. All professional programmers have studied distributed design and this thinking is automatic, even under pressure. All engineers think about architectural problems from the get go. This is taught in degree courses, for crying out loud.
How does a company attract nothing but amateurs?
Admin
Thats a great one!! Doh!
Admin
The issue, as I understand it, is that the component that does the "encryption/decryption" isnt thread-safe - and its instance is being shared among many concurrent web requests. So if Request-1 instantiates it and begins setting properties, but Request-2 starts setting properties which stomps on the values set by Request-1 -- so they both wind up with un-decryptable results. Of course bench-testing this wouldnt have revealed the problem because typically only 1 testing client is running, so you wouldnt get the "stepping over each other" problem.
OOps. Problem is reasonably solved by changing the threading model of the component (assuming its possible), or atomizing the transaction with semaphores.
Admin
I love webservice RPC.
Admin
Because "this" is a local, pushed onto the stack at the time of the call, and nobody else should be changing values in the middle of the stack.
It's still a really poor design to have to work around a race condition, rather than preventing it in the first place.
Admin
Boy, sure would be nice if this forum software didn't barf all over text from Opera.
Admin
BTW, FIRST POINTER!
( self-pointer to http://www.thedailywtf.com/forums/71014/ShowPost.aspx )
Admin
Isn't it great how debugged, tested, then released "libraries" have been replaced by flaky centralized slow complex resource-hungry "web services"?
PROGRESS!
Admin
LAST!!!!!!1111
Admin
Not really....
Admin
Low. Pay. Scale.
Admin
New? For me, when someone claims that he cannot be wrong, I immediately downgrade his trustworthiness. Experience has shown me that such people almost certainly do not check their work anywhere near enough.
Sincerely,
Gene Wirchenko
Admin
There are two WTF's here:
First, the idea that any kind of synch object is out of the question because it would hurt performace too much, when clearly there is a critical resource being shared.
Second, the poster thinks the 'this' pointer is that critical resource, and that someone can set it to null.
repeat after me:
you can't touch this,
can't touch this,
can't touch this.
It is easy to remember if you just set it to a little music.
Frist!!11
Admin
I am a former co-worker of Oliver's. I'm pretty sure that you hit the nail right on the head with this statement. I can picture the single QA tester sitting in her cubicle banging away at each application in the system individually and never coming close to simulating the production environment.
This is not to blame the QA tester; the mental picture just makes me chuckle. A proper environment for realistic testing wouldn't really be considered at Oliver's employer because it would cost money, at least until something really, really bad (like this) happened. It was definitely a fire fighting mentality if there ever was one.
I only worked there for a year and a half, but I could tell you numerous stories about management's decisions that would either make you shoot your beverage of choice out of your nose or curl up in a fetal position, depending on your sense of humor. Just ask Oliver about the money they didn't spend on an HVAC overhaul for the dev/test server room and how those servers fared recently when AC stopped working and the room temp reached 100 degrees F. It would appear that the choice of "Encryption Initiative" developers follows the same decision making pattern.
I left way before "The Encryption Initiative" - thank goodness. I'm sure that some blame would have fallen in my lap had I been there for this mess (everything is always the DBA's fault - right?!?).
Admin
^_^
Admin
Webservices are stateless by nature--thread-safe relates to webservices as pickles to ice cream.
Admin
Not just amateurs, but a crack team of the _best_ amateur developers.
dZ.
Admin
Well, to be fair, thread safety CAN come into play in web services. We have a couple of web services that make platform-invoke calls into old DLLs that are NOT re-entrant or thread-safe, and we have to write a bit of synch-lock code. But yeah, that's nowhere CLOSE to the issue here.
Admin
I thought the first "o" in Klozoff was pronounced like "ah", so it went completely over my head.
Admin
I have read with interest all the replies to my impromptu piece. I still stand by my position.
I have several thousand instances of a single class. The second thread (the timer one) has read-only access to most of the class EXCEPT for the timer-related items. The main thread has full access to EVERYTHING except the timer-related stuff.
It so happens that there was a POSSIBLE race condition where one of the member pointers could be reset while it is in use. I actually saw it happen only when I ran it on a true MULTI-PROCESSOR system. On a single processor system, your thread wouldn't be pre-empted in the middle of a function if the next line happens to be an in-line function (rather than an actual funciton call). That rule wouldn't apply to a true multi-processor system however, and THAT was the reason the race condition showed up. I plugged it using the technique used by MFC in its GetSafeHwnd() function.(i.e. checking for this == NULL).
To 'gremlin': It certainly wasn't if(pSomeObject = NULL). That would have made it crash a few million times a second. :-)
Admin
<FONT face=Arial><FONT size=1>Yeah this is how the planning meeting went:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><o:p></o:p></FONT></FONT>
<FONT face=Arial><FONT size=1>Executive: "Have the client send data centrally so we can track who uses our fancy encryption. We might be able to charge by transaction."<o:p></o:p></FONT></FONT>
<FONT face=Arial size=1>Developer: “So you want me to send the un-encrypted data over the public Internet?”</FONT>
<FONT face=Arial size=1>Executive: “Well…”</FONT>
<FONT face=Arial size=1>Sales person cuts off executive with: “I have a shiny Mercedes!”</FONT>
<FONT face=Arial size=1>Executive talking louder then normal: “They [hackers] won’t know about our fancy encryption stuff… right? They will be trying to snoop (trying to use a buzz word) our transactions.”</FONT>
<FONT face=Arial size=1>Developer: “Um…”</FONT>
<FONT face=Arial size=1>Sales person cuts off developer with: “My girl friend has fake boobs!”</FONT>
<FONT face=Arial size=1>Developer with vein pumping on forehead: “Okay. I think your right. That sounds like a plan. Do I get a commission off of each transaction?”</FONT>
<FONT face=Arial size=1>Executive leaves as developer is talking.</FONT>
<FONT face=Arial><FONT size=1>Sales person: “You’re funny. Commissions are for the sales…” Get’s distracted by shiny object on conference room table.<o:p></o:p></FONT></FONT>
<FONT face=Arial size=1>Developer leaves with two doughnuts while sales person grunts like a chimp.</FONT>
Admin
Come on now, this is OS 101 stuff. Apparently, their best skipped class when the topic turned to stateless vs stateful and atomic operations.
Admin
Semaphores would be overkill in this case, if they ever worked. The problem lies in the RPC marshalling itself. It would make much more sense to have all 3 parameters in one request:
RPC_Encrypt(KEY,ID,MSG)
Otherwise the service would be queueing up all clients, which is super inefficient.
Admin
To Mr. " if(this == NULL) return FALSE; TestSomethingAndReturnResult;" and everyone else on that thread:
First, just want to remind everyone that yes, "this" can be null. Just try class MyObject { void foo() { if (!this) cout<<"Was Null\n"; } }; int main() { ((MyObject*)0)->foo(); return 0; }
Second, as someone else mentioned, "this" cannot become null after you check it, because it is essentially a local variable, usually stored in a register or in the current stack frame. The only way you could change "this" would be with a pointer-to-a-pointer, and whether it would actually work would depend on how the compiler had compiled/optimized things. In short, it is safe to do a check like this. (but keep reading)
Yes, it sometimes happens that you are in such need of performance that you can't afford synchronization. Especially on a multiprocessor system where synchro would actually be expensive. (they really don't hurt much of anything on single processor systems- nothing but a video game engine would care.... er, hm, what kind of app is this?)
Now, having said all that, I would like to point out that it ISN'T "SAFE" TO USE MULTITHREADING WITHOUT SYNCHRO. Meaning that very ordinary programming practices may blow up on you randomly. Also, just because you try it and it works doesn't mean that it will always work, or never fail. There are a lot of factors in play, and recompiling might make one of your race conditions into a crash. The problem I suspect you need to deal with the most is operating on a deleted object. Scenario: Thread 0: begin function call. Thread 1: find and delete object. Thread 1: free resources. Thread 1: set pointer to null. Thread 0: interrupt. check "this", and see it is not null (see first point) Thread 0: operate on object
At this point, Thread 0 is operating on memory (or whatever resource) that has been deallocated. In the case of file handles, you will get errors from the OS, probably. In the case of memory, you will be playing with memory that could at any moment be reallocated as a different object by Thread 1. If Thread0 and Thread1 see the same memory region as two different types of object, you have the potential for a nice crash.
Now, if you make all sorts of asumptions, like that thread1 never allocates memory, only frees it, and make sure that the destructor never intereferes with the values of the object in such a way that would interfere with a method called on this object, then... yes... you can "safely" pull this off, allowing method calls on freed objects. However, this is evil, and a maintainance nightmare. Don't do it. If you really must have a mechanism like this, try adding all the to-be-deleted objects to a list (and synchronize this list), and setting their pointer to null. When Thread0 returns from the method, it can check the list and run cleanup. Another option is to have an object pool, where you never actually delete objects; just return them to the pool when done, and either synchronize the pool, or only allocate using one thread and only return them using one thread (and use a clever datastructure for it that doesn't need synchronization).
As to the issue at hand, I prefer
to that kluge of checking the "this" pointer. Also note that this is the same mechanism you use when dealing with Soft/WeakReferences in Java:
because the garbage collector can set the weakRef to null at any time, just like it were another thread modifying your ref object.
So in summary, yes, you can write code without using synchronization, but it requires complete mastery of multithreading techniques. If you think you'll have performance problems, TRY IT AND SEE. People like to hand-wave about performance, but bad algorithms cause more performance problems than synchronization or OO techniques. Try it. If the performance hit is noticable and too much to take, only then should you think about going with unsynchronized algorithms.
Admin
For the record, the forum doesn't like lesthan-lessthan as needed by cout. How about:
class MyClass { void foo() { if (!this) printf("Was null"); } };
int main() { ((MyObject*)0)->foo(); return 0; }
Admin
Actually if you implement WS-S then all of your web service calls will be encrypted before being transmitted along the wire.
hopefully if they knew enough about WS to implement one, they know that it is plantext.
Although i wouldn't have thought of invoking 3 diff methods on a remote server first..... maybe the didn't know.
I would've either
Admin
It has been several years since I've done a web application, and I didn't quite get the WTF here. I just assumed that code somewhere else was putting the encryption object in a session variable and using SSL for the transport. Having assumed that the encryption object was being stored as a session variable, and further assuming that multiple documents could be encrpyted in a single session, it didn't seem so stupid to separate the object creation and encrpytion calls, since that way you could avoid redundant object creation.
I didn't entirely understand arguments that the very notion of a cryptography server was bad because it introduced a single point of failure. After all, barring some sort of fallover setup, a database server introduces a single point of failure too. Then I decided the difference is that the database server provides an essential service in controling access to shared data, but the only benefit to the cryptograpy service seems to be some vague notion of ease of administration.
Could this sort of service make sense if you had a trusted, isolated, network, some sort of hardware resource for accelerating encryption, and a need to strongly encrypt documents for eventual distribution outside of the trusted network? Am I trying too hard to find the pony in a pile of manure?
Admin
It's not obvious from the code example, but the web service refered to in encWebSrvc is not something created especially for this request; instead, it's a global object (probably from a pool) shared with other requests. For that reason, race conditions happen where concurrent requests using this service mash up their keys etc. If this was a normal call to a library, it would be very reasonable to separate object creation, key setting and encryption calls, since setting the key probably causes some internal work to initialize the encryption engine, so subsequent requests for that key are much faster if a pre-initialized encryption engine exists.
Admin
It is many years since I did much programming and I don't understand your code sample. But I suspect from the context you are saying the encryption routine is not reentrant (or threadsafe) and that is merely reusable.
These are concepts my colleagues and I learnt about in the early days of multitasking 40 years ago and I think the concepts were well established even then. Even then there were amusing examples of the prolems caused by non reetrant code in the wrong contexts.
See http://en.wikipedia.org/wiki/Reentrant for an explanation of the concept.
Those who don't learn from history are doomed to repeat many old mistakes.
Admin
Try:
SomeObject *p = pSomeObject;
return p != null && p->testSomething();
Captcha: real
Admin
No. Assuming it's like Java's synchronised(this){...}, that locks the object itself, not the pointer. Presumably someone can change the pointer and mess up your code (though the JVM probably keeps a copy of the pointer so it doesn't forget to unlock the object).
captcha: ENTERPRISE (how fitting)
capthca: stomache (?)
captcha: freedom (i keep missing ouyt something)
Admin
Assume your thread will be interrupted between instruction boundaries, because that's where the CPU checks for interrupts.
captha: platinum
Admin
Brillant! All we have to do is send unencrypted data over the network to one central, sniffable server, encrypt it, and then send it back. What could go wrong! Well, except that damn stateless HTTP server. Next time they should send it via a POST query, that'd hide the plaintext from those nasty hackers, too!
Admin
Actually, it was done before I started there, and you started before I did.
Of course! At least that's the case now that I'm the "DBA"...
How you doin', btw?
Admin
TEST REPLY
Admin
Another classic WTF which contains code/design which is just plain wrong on so many levels.
Why even use "Web Services", what's wrong with a plain old COM object, DLL, etc. Can't imagine what the "pitch" must have been:
i) Single point of failure
ii) Reduced transaction through-put
iii) Less secure
Must have been a hard sell :P
Admin
You still workin' there and working triplicate jobs? I'd cut my losses and bail. That place drives you so batty your autonomous nerves system starts to give out and your sperm count goes down not long after you hire on.
Admin
Sorry for my syntax, but English is not my mother language.
I was quite astonished by someone even thinking of 3 remote calls through network for a single operation... not mentioning all the problems of security and the bugs creeping in.
But I think the real WTF lies in the comments there:
I think the real WTF lies in the arrogance of most commenters who themselves trip on the same issues they are laughing at.
Really guys, humility is at the heart of our daily work.