Ticket #1155 (new defect)

Opened 2 years ago

Last modified 8 months ago

Session handler is not ajax safe -- it needs a row-level lock

Reported by: ddebernardy Owned by:
Priority: major Milestone: 0.8
Component: Habari Core Software Version: SVN
Keywords: sessions Cc:

Description

When dealing with sessions, it is important to lock database rows until the session is closed (which ought to be done as early as possible in the script).

Failure to do so can introduce concurrent write problems when handling ajax:

  • Page loads, and fires a few asynchronous requests to the server
  • These requests concurrently mess around with session data, and overwrite session data
  • On the next page load, the session's content is random at best

The row-level locking syntax for reference:

See also my next ticket, on sessions as well.

Change History

comment:1 Changed 2 years ago by ddebernardy

For reference, as discussed in IRC following up on a question of how it's done using memcache, and how it could be done in SQLite:

if memory serves, what the memcached guy and I discussed, basically, was this:

  • increment a counter (it's the only atomic thing you can do using memcache)
  • if counter's value is 1, fine (you're alone)
  • if not, resolve conflict as so by setting a token using memcache->add(): (that one will fail if the key exists already)
  • if you succeed, you acquire the session. you release the token when you're done using memcache->delete(), and then you decrement the counter.
  • if you fail, you sleep. then try again a few ms later, until you successfully set your token

what he ended up coding might differ a bit, but that's the gist of what I was suggesting him when I had him look into introduce locks for sessions. it might work too as a workaround for sqlite

comment:2 Changed 2 years ago by michaeltwofish

  • Keywords sessions added

comment:3 Changed 2 years ago by ddebernardy

Related: #1105, #1156, #1157

comment:4 Changed 14 months ago by chrismeller

  • Milestone changed from Undetermined to 0.8

Using native row-level locking is going to be difficult. InnoDB supports it under MySQL, but MyISAM does not (table-level only). I don't think SQLite supports locking at all, and I have no clue about Postgres (though I imagine it supports row-level locking). That leaves us with the possibility of emulating it, which can get very messy very fast.

There's really not a lot of data written to the session, at least for core functionality. Have you actually run into a problem, or is this just a proof of concept type thing?

comment:5 follow-up: ↓ 6 Changed 8 months ago by chrismeller

While I'm reading it, it appears that session_start() is a blocking operation and should avoid this problem:  http://tomrawcliffe.co.uk/blog/2011/04/session_start-blocking-in-php/

comment:6 in reply to: ↑ 5 Changed 8 months ago by michaeltwofish

Replying to chrismeller:

While I'm reading it, it appears that session_start() is a blocking operation and should avoid this problem:  http://tomrawcliffe.co.uk/blog/2011/04/session_start-blocking-in-php/

The comments suggest that it's only blocking if using file-based sessions.

Note: See TracTickets for help on using tickets.