Skip to content

PHP 5.6 rfc session lock #628

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 103 additions & 28 deletions ext/session/mod_files.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ typedef struct {
} ps_files;

ps_module ps_mod_files = {
PS_MOD_SID(files)
PS_MOD_UPDATE_TIMESTAMP(files)
};


Expand Down Expand Up @@ -118,7 +118,7 @@ static void ps_files_close(ps_files *data)
}
}

static void ps_files_open(ps_files *data, const char *key TSRMLS_DC)
static int ps_files_open(ps_files *data, const char *key TSRMLS_DC)
{
char buf[MAXPATHLEN];
struct stat sbuf;
Expand All @@ -133,11 +133,11 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC)

if (php_session_valid_key(key) == FAILURE) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,'");
return;
return FAILURE;
}

if (!ps_files_path_create(buf, sizeof(buf), data, key)) {
return;
return FAILURE;
}

data->lastkey = estrdup(key);
Expand All @@ -164,6 +164,7 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC)
return;
}
#endif

flock(data->fd, LOCK_EX);

#ifdef F_SETFD
Expand All @@ -174,12 +175,17 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "fcntl(%d, F_SETFD, FD_CLOEXEC) failed: %s (%d)", data->fd, strerror(errno), errno);
}
#endif
return SUCCESS;
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "open(%s, O_RDWR) failed: %s (%d)", buf, strerror(errno), errno);
return FAILURE;
}
}

return SUCCESS;
}


static int ps_files_cleanup_dir(const char *dirname, int maxlifetime TSRMLS_DC)
{
DIR *dir;
Expand Down Expand Up @@ -233,6 +239,7 @@ static int ps_files_cleanup_dir(const char *dirname, int maxlifetime TSRMLS_DC)
return (nrdels);
}


static int ps_files_key_exists(ps_files *data, const char *key TSRMLS_DC)
{
char buf[MAXPATHLEN];
Expand All @@ -250,6 +257,12 @@ static int ps_files_key_exists(ps_files *data, const char *key TSRMLS_DC)

#define PS_FILES_DATA ps_files *data = PS_GET_MOD_DATA()


/*
* Open save handler. Setup resources that are needed by the handler.
* Files save handler supports splitting session data into multiple
* directories.
*/
PS_OPEN_FUNC(files)
{
ps_files *data;
Expand Down Expand Up @@ -314,6 +327,10 @@ PS_OPEN_FUNC(files)
return SUCCESS;
}


/*
* Close save handler and clean up used resources.
*/
PS_CLOSE_FUNC(files)
{
PS_FILES_DATA;
Expand All @@ -331,32 +348,20 @@ PS_CLOSE_FUNC(files)
return SUCCESS;
}

/*
* Reads specific session ID from session storage.
* PS_READ_FUNC() may have use_strict_mode support in it.
* Alternatively, save handler may use PS_VALIDATE_SID() to check
* session data existence.
*/
PS_READ_FUNC(files)
{
long n;
struct stat sbuf;
PS_FILES_DATA;

/* If strict mode, check session id existence */
if (PS(use_strict_mode) &&
ps_files_key_exists(data, key TSRMLS_CC) == FAILURE) {
/* key points to PS(id), but cannot change here. */
if (key) {
efree(PS(id));
PS(id) = NULL;
}
PS(id) = PS(mod)->s_create_sid((void **)&data, NULL TSRMLS_CC);
if (!PS(id)) {
return FAILURE;
}
if (PS(use_cookies)) {
PS(send_cookie) = 1;
}
php_session_reset_id(TSRMLS_C);
PS(session_status) = php_session_active;
}

ps_files_open(data, PS(id) TSRMLS_CC);
/* php_session_read_data() calls PS_VALIDATE_SID() for use_strict_mode support */
ps_files_open(data, key TSRMLS_CC);
if (data->fd < 0) {
return FAILURE;
}
Expand Down Expand Up @@ -394,19 +399,26 @@ PS_READ_FUNC(files)
return SUCCESS;
}


/*
* Write session data.
* PS_WRITE_FUNC() should write session data unconditionally.
*/
PS_WRITE_FUNC(files)
{
long n;
PS_FILES_DATA;
struct stat sbuf;

ps_files_open(data, key TSRMLS_CC);
if (data->fd < 0) {
return FAILURE;
if (ps_files_open(data, key TSRMLS_CC) == FAILURE) {
return FAILURE;
}
}

/* Truncate file if the amount of new data is smaller than the existing data set. */

if (vallen < (int)data->st_size) {
fstat(data->fd, &sbuf);
if (vallen < (int)sbuf.st_size) {
php_ignore_value(ftruncate(data->fd, 0));
}

Expand All @@ -429,6 +441,42 @@ PS_WRITE_FUNC(files)
return SUCCESS;
}


/*
* Update session data.
* PS_UPDATE_TIMESTAMP_FUNC() updates time stamp so that active session would not be purged.
*/
PS_UPDATE_TIMESTAMP_FUNC(files)
{
char buf[MAXPATHLEN];
struct utimbuf newtimebuf;
struct utimbuf *newtime = &newtimebuf;
int ret;
PS_FILES_DATA;

if (!ps_files_path_create(buf, sizeof(buf), data, key)) {
return FAILURE;
}

/* Update mtime */
#ifdef HAVE_UTIME_NULL
newtime = NULL;
#else
newtime->modtime = newtime->actime = time(NULL);
#endif
ret = VCWD_UTIME(buf, newtime);
if (ret == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Utime failed in ps_files_open(): %s", strerror(errno));
}

return SUCCESS;
}


/*
* Delete session data.
* PS_DESTROY_FUNC() should delete session unconditionally.
*/
PS_DESTROY_FUNC(files)
{
char buf[MAXPATHLEN];
Expand All @@ -453,6 +501,13 @@ PS_DESTROY_FUNC(files)
return SUCCESS;
}


/*
* Execute garbage collection.
* Full GC support requires to delete all expired session by this function.
* Files save handler does not delete session when multiple directory is
* used.
*/
PS_GC_FUNC(files)
{
PS_FILES_DATA;
Expand All @@ -468,6 +523,13 @@ PS_GC_FUNC(files)
return SUCCESS;
}


/*
* Create session ID.
* Default php_session_create_id() does not check collision.
* Return valid session ID string.
* Return NULL for failure.
*/
PS_CREATE_SID_FUNC(files)
{
char *sid;
Expand All @@ -492,6 +554,19 @@ PS_CREATE_SID_FUNC(files)
}


/*
* Check session ID existence for use_strict_mode support.
* Return SUCCESS for valid(already exsting session).
* Return FAILURE for invalid(non-existing session).
*/
PS_VALIDATE_SID_FUNC(files)
{
PS_FILES_DATA;

return ps_files_key_exists(data, key TSRMLS_CC);
}


/*
* Local variables:
* tab-width: 4
Expand Down
2 changes: 1 addition & 1 deletion ext/session/mod_files.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
extern ps_module ps_mod_files;
#define ps_files_ptr &ps_mod_files

PS_FUNCS_SID(files);
PS_FUNCS_UPDATE_TIMESTAMP(files);

#endif
65 changes: 50 additions & 15 deletions ext/session/mod_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,25 @@
#include "mod_user.h"

ps_module ps_mod_user = {
PS_MOD_SID(user)
PS_MOD_UPDATE_TIMESTAMP(user)
};

#define SESS_ZVAL_LONG(val, a) \
#define SESS_ZVAL_LONG(a, val) \
{ \
MAKE_STD_ZVAL(a); \
ZVAL_LONG(a, val); \
}

#define SESS_ZVAL_STRING(vl, a) \
#define SESS_ZVAL_STRING(a, val) \
{ \
char *__vl = vl; \
SESS_ZVAL_STRINGN(__vl, strlen(__vl), a); \
MAKE_STD_ZVAL(a); \
ZVAL_STRING(a, val, 1); \
}

#define SESS_ZVAL_STRINGN(vl, ln, a) \
#define SESS_ZVAL_STRINGL(a, val, len) \
{ \
MAKE_STD_ZVAL(a); \
ZVAL_STRINGL(a, vl, ln, 1); \
ZVAL_STRINGL(a, val, len, 1); \
}

static zval *ps_call_handler(zval *func, int argc, zval **argv TSRMLS_DC)
Expand Down Expand Up @@ -84,12 +84,11 @@ PS_OPEN_FUNC(user)
if (PSF(open) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING,
"user session functions not defined");

return FAILURE;
}

SESS_ZVAL_STRING((char*)save_path, args[0]);
SESS_ZVAL_STRING((char*)session_name, args[1]);
SESS_ZVAL_STRING(args[0], save_path);
SESS_ZVAL_STRING(args[1], session_name);

retval = ps_call_handler(PSF(open), 2, args TSRMLS_CC);
PS(mod_user_implemented) = 1;
Expand Down Expand Up @@ -130,7 +129,7 @@ PS_READ_FUNC(user)
zval *args[1];
STDVARS;

SESS_ZVAL_STRING((char*)key, args[0]);
SESS_ZVAL_STRING(args[0], key);

retval = ps_call_handler(PSF(read), 1, args TSRMLS_CC);

Expand All @@ -151,8 +150,8 @@ PS_WRITE_FUNC(user)
zval *args[2];
STDVARS;

SESS_ZVAL_STRING((char*)key, args[0]);
SESS_ZVAL_STRINGN((char*)val, vallen, args[1]);
SESS_ZVAL_STRING(args[0], key);
SESS_ZVAL_STRINGL(args[1], val, vallen);

retval = ps_call_handler(PSF(write), 2, args TSRMLS_CC);

Expand All @@ -164,7 +163,7 @@ PS_DESTROY_FUNC(user)
zval *args[1];
STDVARS;

SESS_ZVAL_STRING((char*)key, args[0]);
SESS_ZVAL_STRING(args[0], key);

retval = ps_call_handler(PSF(destroy), 1, args TSRMLS_CC);

Expand All @@ -176,7 +175,7 @@ PS_GC_FUNC(user)
zval *args[1];
STDVARS;

SESS_ZVAL_LONG(maxlifetime, args[0]);
SESS_ZVAL_LONG(args[0], maxlifetime);

retval = ps_call_handler(PSF(gc), 1, args TSRMLS_CC);

Expand Down Expand Up @@ -215,6 +214,42 @@ PS_CREATE_SID_FUNC(user)
return php_session_create_id(mod_data, newlen TSRMLS_CC);
}

PS_VALIDATE_SID_FUNC(user)
{
/* maintain backwards compatibility */
if (PSF(validate_sid) != NULL) {
zval *args[1];
STDVARS;

SESS_ZVAL_STRING(args[0], key);

retval = ps_call_handler(PSF(validate_sid), 1, args TSRMLS_CC);

FINISH;
}

/* dummy function defined by PS_MOD */
return php_session_validate_sid(mod_data, key TSRMLS_CC);
}

PS_UPDATE_TIMESTAMP_FUNC(user)
{
zval *args[2];
STDVARS;

SESS_ZVAL_STRING(args[0], key);
SESS_ZVAL_STRINGL(args[1], val, vallen);

/* maintain backwards compatibility */
if (PSF(update_timestamp) != NULL) {
retval = ps_call_handler(PSF(update_timestamp), 2, args TSRMLS_CC);
} else {
retval = ps_call_handler(PSF(write), 2, args TSRMLS_CC);
}

FINISH;
}

/*
* Local variables:
* tab-width: 4
Expand Down
2 changes: 1 addition & 1 deletion ext/session/mod_user.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@
extern ps_module ps_mod_user;
#define ps_user_ptr &ps_mod_user

PS_FUNCS_SID(user);
PS_FUNCS_UPDATE_TIMESTAMP(user);

#endif
Loading