HNHacker News
TopNewBestAskShowJobs

wulczer

1,457 karma · joined February 16, 2011

Engineer at New Relic (personal email: wulczer-hn@wulczer.org)

[ my public key: https://keybase.io/wulczer; my proof: https://keybase.io/wulczer/sigs/g46dYvOOsEpYFfTEQUY4Hwj5x_gO3JSvfDNXnd4pjvI ]

submissionscomments
wulczer··on Why aren't you commenting your code?
Yeah, I agree, it's a question of cost vs benefit.

A bunch of tests that check trivial cases is not helpful at all, a well-maintained suite of tests is very useful.

What I mean is that a bunch of documentation that only states the obvious is not helpful at all. A set of well-maintained (!) code comments can make navigating unfamiliar code much, much easier.

wulczer··on Why aren't you commenting your code?

  > Comments - like documentation - are a liability.
Tests, too. But you wouldn't advocate not having tests, right?
wulczer··on Why aren't you commenting your code?
Bad comments are like bad tests, they're bad. Good comments, like good tests, are a boon for complex software.
wulczer··on Why aren't you commenting your code?
I think it is helpful to know if the check is just a sanity check or if there's an already known set of conditions can lead to that particular error.

The function comments I also find very useful. Read a few of them and see how much information they carry. Preconditions for the function, reasons why it does what it does, assumptions it makes... These functions are used from throughout the code and it's important to document them well.

I'm purposefully not quoting specific parts of the file, because of course if you look at each and every one of them, you'll find a few that could be improved. But the OP asked for a well commented code base and if PostgreSQL is not one, then I don't know what would be.

wulczer··on Why aren't you commenting your code?
https://github.com/postgres/postgres/blob/master/src/backend...

In general, most of Postgres code.

wulczer··on Via introduces APC Paper: A $99 Android PC
So disappointed when I went to http://apc.io/products/scissors/ and got a 404 :(
wulczer··on How our users exploited concurrency and how we fixed it
I believe this won't work on PostgreSQL, which will always say one row has been updated, even if the new value is the same as the old value.

There are numerous ways around that, from less fancy to really fancy.

  1. use SELECT FOR UPDATE, which will lock the row (I'd say that's the normal way)

  session1> BEGIN;
  session1> SELECT * FROM goals WHERE player_id = ? FOR UPDATE
  session2> BEGIN;
  session2> SELECT * FROM goals WHERE player_id = ? FOR UPDATE
  # session2 is now hanging
  session1> UPDATE goals SET completed = true WHERE goal_id = ?
  session1> UPDATE players SET points = points + 1 WHERE player_id = ?
  session1> COMMIT;
  # session2 now proceeds, sees that the goal has been completed, forfeits awarding the reward

  2. use suppress_reduntant_updates_trigger (fun)

  session> CREATE TRIGGER suppress_goal_t BEFORE UPDATE ON goals FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
  session> UPDATE goals SET completed = true WHERE goal_id = ?
  UPDATE 1
  session> UPDATE goals SET completed = true WHERE goal_id = ?
  UPDATE 0
  # now you can use the approach mentioned in the article

  3. use true serialisability
  session1> BEGIN;
  session1> SET transaction_isolation TO serializable;
  session1> SELECT * FROM goals WHERE player_id = ?
  session2> BEGIN;
  session2> SET transaction_isolation TO serializable;
  session2> SELECT * FROM goals WHERE player_id = ?
  session1> UPDATE goals SET completed = true WHERE goal_id = ?
  session1> UPDATE players SET points = points + 1 WHERE player_id = ?
  session1> COMMIT;
  session2> UPDATE goals SET completed = true WHERE goal_id = ?
  ERROR:  could not serialize access due to concurrent update
  # session2 now has to rollback the transaction
There's a few more, but I ran out of steam typing ;) Yay, Postgres!
wulczer··on Password Hijacking Security Incident and Response
I just gave django.contrib.auth.tokens a read and shared my opinion on it :)

I wouldn't roll my own password reset feature if I can just take the builtin one from Django, which is what I did.

wulczer··on Password Hijacking Security Incident and Response
I commented on the other thread, but will repeat here: I really like how Django handles password resets.

No nonce is generated and nothing is stored. The user is emailed a link with her user ID and a token that's a hash of (last login timestamp + the user's ID + the user's (hashed) password + current timestamp). The token is HMAC-signed with the site's secret key.

This way the token automatically expires if the user either successfully changes her password (the password hash will change) or manages to log in (last login timestamp changes).

It seems that in Django password reset tokens are valid forever, but it would be trivial to add the current timestamp to the token and include it when computing the HMAC signature; then the password reset form would check if the token has been generated recently enough.

I like this method because you never need to touch the database and store tokens; it's all fairly stateless.

wulczer··on Security Vulnerabilities in Heroku
It's interesting how differently Django handles password resets - no nonce is generated.

Instead, the user is emailed a token that's just her user ID, HMAC-signed with the last login date and a secret site key.

You can't generate valid reset links without knowing the secret key and you can't tamper with the one you got because it's HMAC-signed. By adding the last login date to the HMAC you make sure the link can be used only once. After a user resets her password, the last login date is updated to now so the link is no longer valid due to broken HMAC.

I like this solution because it doesn't rely on storing any state anywhere between requesting the reset and completing it.

wulczer··on Exploit Information Leaks in Random Numbers from Python, Ruby and PHP
> (I'm pretty sure the same is true of Python, but I'm less confident of the specifics. I think this is a very fair issue to raise with PHP in general, though.)

Yeah, Python's random module uses MT, but you can use PyCrypto, which provides an API-compatible cryptographically secure module (PyCrypto.Random.random).

wulczer··on Discussion on changing name from PostgreSQL to Postgres
This is a wiki page created to discuss the steps that would have to be taken should the decision to change the name be taken.

As far as I know, the core team's position is that the product is called PostgreSQL, with Postgres being an acceptable alias.

If you ask me, this comic sums up the issue adequately: http://xkcd.com/747/

Alternatively, if you want to have a few laughs, check this out: http://wiki.postgresql.org/wiki/File:05_-_Gabrielle_Roth_-_p...

wulczer··on Rootkit infects Linux web servers
CrowdStrike says that it hooks vfs_read and if the data read contains the line it injects into /etc/rc.local, it is removed from the read buffer.

This means you could just read the file byte-by-byte (I guess runnin dd a couple of times would work), though I haven't tried myself.

wulczer··on Proper use cases for Android UserManager.isUserAGoat()
It can't

http://git.chromium.org/gitweb/?p=chromium.git;a=blob;f=chro...

(link found on some other page, can't remember where)

wulczer··on How Zapier made us support a hundred new services in half an hour
Ah, the ambiguities of the English tongue and the unaware non-native speakers that get ensnared by them!

Anyway, I hope the intended meaning gets through and it was also a case of "shit, people, we need to be on this thing!". So they made us support new services as gas makes a car run, and they also made us do it as a madman makes Sandra Bullock go over 50 mph.

Disclaimer(s): I wrote the original post and I had some beers.

wulczer··on Making Twilio calls from Zabbix
Oh boy, are you in for a treat then :)

Let's just say that there'll be news announced next week...

wulczer··on Google.ie DNS was hacked (now fixed)
Interesting:

  $ dig +short @8.8.8.8 google.ie
  173.194.39.119
  173.194.39.127
  173.194.39.120

  $ dig +short @ns1.farahatz.net google.ie
  119.235.27.219

  $ whois 119.235.27.219
  (...)
  descr:          PT. TEKNOLOGI LINTASLINK
  (...)
wulczer··on Show HN: Online C/C++ to assembly visualizer [Weekend Project]
Well one easy way to increase security would for this to stop running as root.

Please, don't ever run your application code as root. Less so when it's facing the Internet.

wulczer··on PostgreSQL 9.2 released
Yep, the people that can both produce and sell are a rare and very valuable breed, if only because they can actually understand what the other marketers need (or will pay for!).
wulczer··on PostgreSQL 9.2 released
> Some PR or marketing guy wrote them then showed them to the person to whom they'd be attributed to get their ok

I happen to know the guy that AFAIK was in charge of preparing the press release and he's actually a major contributor to the codebase, a geek par excellence and have been nagging people to get him quotes on the development mailing list.

The fact that apart from hacking C code he also knows how to write a catchy press release just makes him all the awesomer :)

wulczer··on Python performance the easy(ish) way
I've tried this with GCC 4.7.1 on Debian x86_64 and did not get it to work in constant time with -O2.

I'm guessing (from the OP's usage of -install_name) that he's been compiling this on OSX. I wonder what did my compiler miss that the OP's didn't?

EDIT: just tried with clang and got constant time behaviour, interesting

EDIT 2: reading the comments in the post, I now suspect it has to do with integer overflow. However, compiling with -fwrapv did not change anything. Need to dig into it more.

EDIT 3: it seem that clang simply notices that the computation can be done in constant time, whereas gcc does not. I'm not sure if it's actually useful in real world code, but it's certainly somewhat magical to see a compiler understand that you can substitute the entire loop with a simple calculation

wulczer··on Why host and write a blog?
I like Matt Hempey's take on the problem:

  blog blog blog it all, blog it if it's big or small
  blog at the cineplex, blog while you're having sex
  blog in the locker room, babies blogging in the womb
  blog even if you're wrong, won't you blog about this song?
wulczer··on Samwers Clone Stripe
That's right if you use "should" instead of "shall".
wulczer··on Samwers Clone Stripe
Still evaluating. But we definitely don't want to stay there.
wulczer··on Samwers Clone Stripe
Ouch, that's a big minus from the point of view of an European company - not having to look for another app to generate invoices or futz around with generating your own was nice.

The specific issue with Recurly that we had is that they silently changed their platform to perform VIES validation on all VAT numbers. While this makes sense for transactions with entities from outside of the merchant's country, validating VAT numbers for German-to-German or Spanish-to-Spanish transactions is silly. Not only do such transactions always get charged VAT, but it's possible that a given string is a valid VAT number and yet is not present in VIES. Since you will pay (and therefore charge the customer) VAT for same-country transactions anyway, you don't care if the number that the customer provided is valid according to VIES.

This change has cost us a little wave of support tickets and an ugly workaround, in preparation for moving off Recurly.

I firmly believe that a company that gets online recurring payments right in Europe will become a money-printing machine in no time.

wulczer··on Enforcing Different Passwords for Different Sites
I recommend that everyone who read this contemplates this: http://news.ycombinator.com/item?id=3889435 (AKA the voice of reason)
wulczer··on Security questions are salt
Also, i18n.
wulczer··on Productivity Porn
As we all know, every situation in life can be exhaustively and accurately resumed by an XKCD comic.

Here's this thread's: http://xkcd.com/874/

wulczer··on MixPanel tracking API down
Yep, like rprime said, we're sending tracking events from the server (let me plug http://libsaas.net here).

So instead of using mixpanel.track from Javascript, you do an AJAX call to your own server and schedule a Celery job there.

There's an issue with passing Mixpanel's super properties to your server-side handler, but that's the general idea.

wulczer··on MixPanel tracking API down
We just issue Celery jobs to track events in Mixpanel, so if their API is failing, the jobs fail and get retried later on.

If we get too many messages accumulated in the queue where these jobs go, we just purge it (better lose that data than let RabbitMQ die because of memory exhaustion). Although there have to be a whole damn lot of events there for us to actually notice

← PreviousPage 2 of 8Next →