Codeigniter 3 upgrade session lock causing issues
We've recently upgraded an old Codeigniter app from 2.1.0 to 3.1.9, and everything has gone smoothly. Except, that the new session locking is causing issues and I'm wondering the proper way to fix it.
The app uses AJAX heavily, however most of the AJAX calls don't write to the session and don't seem to break it.
Here is an example of the issue: there is a GUI with checkboxes, and when the input is changed (a checkbox is checked or unchecked) an AJAX call was made. On the other end of that AJAX call which boxes were checked were written to session so that they would be remembered from visit to visit. However, if you checked/unchecked multiple boxes causing multiple AJAX calls to go out, you would end up getting logged out. Similar behavior has been discovered around the app, all where session writes are happening.
I've tried implementing session_write_close()
as suggested by the Codeigniter documentation but that only half worked in some spots, and caused more issues in area where there were no issues before. The app has a few endpoints that do all the work and all work flows share, so fixing the endpoint where the session writes are happening with session_write_close()
breaks other script calls when they continue to need the session.
The short term solution I've come up with is to debounce the AJAX calls (which helps but doesn't solve the problem by itself) and to disable inputs until the AJAX call has finished.
Is there a better long term solution? Ultimately this app is being phased out, so spending a long time rewriting it isn't feasible.
php ajax codeigniter session
add a comment |
We've recently upgraded an old Codeigniter app from 2.1.0 to 3.1.9, and everything has gone smoothly. Except, that the new session locking is causing issues and I'm wondering the proper way to fix it.
The app uses AJAX heavily, however most of the AJAX calls don't write to the session and don't seem to break it.
Here is an example of the issue: there is a GUI with checkboxes, and when the input is changed (a checkbox is checked or unchecked) an AJAX call was made. On the other end of that AJAX call which boxes were checked were written to session so that they would be remembered from visit to visit. However, if you checked/unchecked multiple boxes causing multiple AJAX calls to go out, you would end up getting logged out. Similar behavior has been discovered around the app, all where session writes are happening.
I've tried implementing session_write_close()
as suggested by the Codeigniter documentation but that only half worked in some spots, and caused more issues in area where there were no issues before. The app has a few endpoints that do all the work and all work flows share, so fixing the endpoint where the session writes are happening with session_write_close()
breaks other script calls when they continue to need the session.
The short term solution I've come up with is to debounce the AJAX calls (which helps but doesn't solve the problem by itself) and to disable inputs until the AJAX call has finished.
Is there a better long term solution? Ultimately this app is being phased out, so spending a long time rewriting it isn't feasible.
php ajax codeigniter session
add a comment |
We've recently upgraded an old Codeigniter app from 2.1.0 to 3.1.9, and everything has gone smoothly. Except, that the new session locking is causing issues and I'm wondering the proper way to fix it.
The app uses AJAX heavily, however most of the AJAX calls don't write to the session and don't seem to break it.
Here is an example of the issue: there is a GUI with checkboxes, and when the input is changed (a checkbox is checked or unchecked) an AJAX call was made. On the other end of that AJAX call which boxes were checked were written to session so that they would be remembered from visit to visit. However, if you checked/unchecked multiple boxes causing multiple AJAX calls to go out, you would end up getting logged out. Similar behavior has been discovered around the app, all where session writes are happening.
I've tried implementing session_write_close()
as suggested by the Codeigniter documentation but that only half worked in some spots, and caused more issues in area where there were no issues before. The app has a few endpoints that do all the work and all work flows share, so fixing the endpoint where the session writes are happening with session_write_close()
breaks other script calls when they continue to need the session.
The short term solution I've come up with is to debounce the AJAX calls (which helps but doesn't solve the problem by itself) and to disable inputs until the AJAX call has finished.
Is there a better long term solution? Ultimately this app is being phased out, so spending a long time rewriting it isn't feasible.
php ajax codeigniter session
We've recently upgraded an old Codeigniter app from 2.1.0 to 3.1.9, and everything has gone smoothly. Except, that the new session locking is causing issues and I'm wondering the proper way to fix it.
The app uses AJAX heavily, however most of the AJAX calls don't write to the session and don't seem to break it.
Here is an example of the issue: there is a GUI with checkboxes, and when the input is changed (a checkbox is checked or unchecked) an AJAX call was made. On the other end of that AJAX call which boxes were checked were written to session so that they would be remembered from visit to visit. However, if you checked/unchecked multiple boxes causing multiple AJAX calls to go out, you would end up getting logged out. Similar behavior has been discovered around the app, all where session writes are happening.
I've tried implementing session_write_close()
as suggested by the Codeigniter documentation but that only half worked in some spots, and caused more issues in area where there were no issues before. The app has a few endpoints that do all the work and all work flows share, so fixing the endpoint where the session writes are happening with session_write_close()
breaks other script calls when they continue to need the session.
The short term solution I've come up with is to debounce the AJAX calls (which helps but doesn't solve the problem by itself) and to disable inputs until the AJAX call has finished.
Is there a better long term solution? Ultimately this app is being phased out, so spending a long time rewriting it isn't feasible.
php ajax codeigniter session
php ajax codeigniter session
asked Nov 26 '18 at 14:34
sharfsharf
1,39721131
1,39721131
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
The only long-term solution is to properly use session_write_close()
.
As you undoubtedly understand, session data is locked so only one script at any time can write to the session's persistent datastore. Session locking prevents hard to troubleshoot concurrency bugs and is more secure.
Without seeing your implementation it's really hard, er... impossible to offer any precise advice. Here are some things to consider that might help sort out the mess.
Either do ALL or NONE of the session writes in the AJAX response functions. (By "AJAX response function" I mean the PHP controller/method
value of the AJAX url.)
With the ALL approach call session_write_close()
in the "main" script before making any AJAX requests. Keep in mind that $_SESSION
is not affected by session_write_close()
. All $_SESSION
items in the main script will remain accessible so you can reliably read the values. However, changes made to $_SESSION
will not be written because, as far as PHP is concerned, the session is closed. But that's only true for the script that calls session_write_close()
.
With the NONE approach you may still need to read session data. In that case it would be wise to have the AJAX response functions call session_write_close
as soon as possible to minimize the time concurrent requests are blocked. The call is more important for functions that require significant time to execute. If the script execution time is short then the explicit call to session_write_close()
is not needed. If at all possible, i.e. no need to read session data, then not loading the session
class might result in cleaner code. It would definitely eliminate any chance of concurrent request blocking.
Don't try to test session behavior by using multiple tabs to the same app on the same browser.
Consider using $config['sess_time_to_update'] = 0;
and then explicitly call $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
when and where it makes sense that the session id needs to be changed, i.e. right after login; right after a redirect to a "sensitive" page; etc.
What follows next is offered with a large amount of trepidation. I've tested this using the "files" driver, but not extensively. So, buyer beware.
I found that it is possible to "re-start" a session by calling the PHP function session_start()
after session_write_close()
has been used. CodeIgniter will open and read the session datastore and rebuild the $_SESSION
superglobal. It's now possible to change session data and it will be written when script execution ends - or with another call to session_write_close()
.
This makes sense because session_write_close()
does not "do" anything to the CodeIgniter session
object. The class is still instantiated and configured. CodeIgniter's custom SessionHandlerInterface
is used to open, read, and write session data after session_start()
is called.
Maybe this apparent functionality can be used to solve your problems. In case I wasn't clear earlier - use at your own risk!
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to putsession_write_close()
, unless I experiment withsession_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!
– sharf
Nov 27 '18 at 14:08
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53483367%2fcodeigniter-3-upgrade-session-lock-causing-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The only long-term solution is to properly use session_write_close()
.
As you undoubtedly understand, session data is locked so only one script at any time can write to the session's persistent datastore. Session locking prevents hard to troubleshoot concurrency bugs and is more secure.
Without seeing your implementation it's really hard, er... impossible to offer any precise advice. Here are some things to consider that might help sort out the mess.
Either do ALL or NONE of the session writes in the AJAX response functions. (By "AJAX response function" I mean the PHP controller/method
value of the AJAX url.)
With the ALL approach call session_write_close()
in the "main" script before making any AJAX requests. Keep in mind that $_SESSION
is not affected by session_write_close()
. All $_SESSION
items in the main script will remain accessible so you can reliably read the values. However, changes made to $_SESSION
will not be written because, as far as PHP is concerned, the session is closed. But that's only true for the script that calls session_write_close()
.
With the NONE approach you may still need to read session data. In that case it would be wise to have the AJAX response functions call session_write_close
as soon as possible to minimize the time concurrent requests are blocked. The call is more important for functions that require significant time to execute. If the script execution time is short then the explicit call to session_write_close()
is not needed. If at all possible, i.e. no need to read session data, then not loading the session
class might result in cleaner code. It would definitely eliminate any chance of concurrent request blocking.
Don't try to test session behavior by using multiple tabs to the same app on the same browser.
Consider using $config['sess_time_to_update'] = 0;
and then explicitly call $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
when and where it makes sense that the session id needs to be changed, i.e. right after login; right after a redirect to a "sensitive" page; etc.
What follows next is offered with a large amount of trepidation. I've tested this using the "files" driver, but not extensively. So, buyer beware.
I found that it is possible to "re-start" a session by calling the PHP function session_start()
after session_write_close()
has been used. CodeIgniter will open and read the session datastore and rebuild the $_SESSION
superglobal. It's now possible to change session data and it will be written when script execution ends - or with another call to session_write_close()
.
This makes sense because session_write_close()
does not "do" anything to the CodeIgniter session
object. The class is still instantiated and configured. CodeIgniter's custom SessionHandlerInterface
is used to open, read, and write session data after session_start()
is called.
Maybe this apparent functionality can be used to solve your problems. In case I wasn't clear earlier - use at your own risk!
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to putsession_write_close()
, unless I experiment withsession_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!
– sharf
Nov 27 '18 at 14:08
add a comment |
The only long-term solution is to properly use session_write_close()
.
As you undoubtedly understand, session data is locked so only one script at any time can write to the session's persistent datastore. Session locking prevents hard to troubleshoot concurrency bugs and is more secure.
Without seeing your implementation it's really hard, er... impossible to offer any precise advice. Here are some things to consider that might help sort out the mess.
Either do ALL or NONE of the session writes in the AJAX response functions. (By "AJAX response function" I mean the PHP controller/method
value of the AJAX url.)
With the ALL approach call session_write_close()
in the "main" script before making any AJAX requests. Keep in mind that $_SESSION
is not affected by session_write_close()
. All $_SESSION
items in the main script will remain accessible so you can reliably read the values. However, changes made to $_SESSION
will not be written because, as far as PHP is concerned, the session is closed. But that's only true for the script that calls session_write_close()
.
With the NONE approach you may still need to read session data. In that case it would be wise to have the AJAX response functions call session_write_close
as soon as possible to minimize the time concurrent requests are blocked. The call is more important for functions that require significant time to execute. If the script execution time is short then the explicit call to session_write_close()
is not needed. If at all possible, i.e. no need to read session data, then not loading the session
class might result in cleaner code. It would definitely eliminate any chance of concurrent request blocking.
Don't try to test session behavior by using multiple tabs to the same app on the same browser.
Consider using $config['sess_time_to_update'] = 0;
and then explicitly call $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
when and where it makes sense that the session id needs to be changed, i.e. right after login; right after a redirect to a "sensitive" page; etc.
What follows next is offered with a large amount of trepidation. I've tested this using the "files" driver, but not extensively. So, buyer beware.
I found that it is possible to "re-start" a session by calling the PHP function session_start()
after session_write_close()
has been used. CodeIgniter will open and read the session datastore and rebuild the $_SESSION
superglobal. It's now possible to change session data and it will be written when script execution ends - or with another call to session_write_close()
.
This makes sense because session_write_close()
does not "do" anything to the CodeIgniter session
object. The class is still instantiated and configured. CodeIgniter's custom SessionHandlerInterface
is used to open, read, and write session data after session_start()
is called.
Maybe this apparent functionality can be used to solve your problems. In case I wasn't clear earlier - use at your own risk!
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to putsession_write_close()
, unless I experiment withsession_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!
– sharf
Nov 27 '18 at 14:08
add a comment |
The only long-term solution is to properly use session_write_close()
.
As you undoubtedly understand, session data is locked so only one script at any time can write to the session's persistent datastore. Session locking prevents hard to troubleshoot concurrency bugs and is more secure.
Without seeing your implementation it's really hard, er... impossible to offer any precise advice. Here are some things to consider that might help sort out the mess.
Either do ALL or NONE of the session writes in the AJAX response functions. (By "AJAX response function" I mean the PHP controller/method
value of the AJAX url.)
With the ALL approach call session_write_close()
in the "main" script before making any AJAX requests. Keep in mind that $_SESSION
is not affected by session_write_close()
. All $_SESSION
items in the main script will remain accessible so you can reliably read the values. However, changes made to $_SESSION
will not be written because, as far as PHP is concerned, the session is closed. But that's only true for the script that calls session_write_close()
.
With the NONE approach you may still need to read session data. In that case it would be wise to have the AJAX response functions call session_write_close
as soon as possible to minimize the time concurrent requests are blocked. The call is more important for functions that require significant time to execute. If the script execution time is short then the explicit call to session_write_close()
is not needed. If at all possible, i.e. no need to read session data, then not loading the session
class might result in cleaner code. It would definitely eliminate any chance of concurrent request blocking.
Don't try to test session behavior by using multiple tabs to the same app on the same browser.
Consider using $config['sess_time_to_update'] = 0;
and then explicitly call $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
when and where it makes sense that the session id needs to be changed, i.e. right after login; right after a redirect to a "sensitive" page; etc.
What follows next is offered with a large amount of trepidation. I've tested this using the "files" driver, but not extensively. So, buyer beware.
I found that it is possible to "re-start" a session by calling the PHP function session_start()
after session_write_close()
has been used. CodeIgniter will open and read the session datastore and rebuild the $_SESSION
superglobal. It's now possible to change session data and it will be written when script execution ends - or with another call to session_write_close()
.
This makes sense because session_write_close()
does not "do" anything to the CodeIgniter session
object. The class is still instantiated and configured. CodeIgniter's custom SessionHandlerInterface
is used to open, read, and write session data after session_start()
is called.
Maybe this apparent functionality can be used to solve your problems. In case I wasn't clear earlier - use at your own risk!
The only long-term solution is to properly use session_write_close()
.
As you undoubtedly understand, session data is locked so only one script at any time can write to the session's persistent datastore. Session locking prevents hard to troubleshoot concurrency bugs and is more secure.
Without seeing your implementation it's really hard, er... impossible to offer any precise advice. Here are some things to consider that might help sort out the mess.
Either do ALL or NONE of the session writes in the AJAX response functions. (By "AJAX response function" I mean the PHP controller/method
value of the AJAX url.)
With the ALL approach call session_write_close()
in the "main" script before making any AJAX requests. Keep in mind that $_SESSION
is not affected by session_write_close()
. All $_SESSION
items in the main script will remain accessible so you can reliably read the values. However, changes made to $_SESSION
will not be written because, as far as PHP is concerned, the session is closed. But that's only true for the script that calls session_write_close()
.
With the NONE approach you may still need to read session data. In that case it would be wise to have the AJAX response functions call session_write_close
as soon as possible to minimize the time concurrent requests are blocked. The call is more important for functions that require significant time to execute. If the script execution time is short then the explicit call to session_write_close()
is not needed. If at all possible, i.e. no need to read session data, then not loading the session
class might result in cleaner code. It would definitely eliminate any chance of concurrent request blocking.
Don't try to test session behavior by using multiple tabs to the same app on the same browser.
Consider using $config['sess_time_to_update'] = 0;
and then explicitly call $this->sess_regenerate((bool) config_item('sess_regenerate_destroy'));
when and where it makes sense that the session id needs to be changed, i.e. right after login; right after a redirect to a "sensitive" page; etc.
What follows next is offered with a large amount of trepidation. I've tested this using the "files" driver, but not extensively. So, buyer beware.
I found that it is possible to "re-start" a session by calling the PHP function session_start()
after session_write_close()
has been used. CodeIgniter will open and read the session datastore and rebuild the $_SESSION
superglobal. It's now possible to change session data and it will be written when script execution ends - or with another call to session_write_close()
.
This makes sense because session_write_close()
does not "do" anything to the CodeIgniter session
object. The class is still instantiated and configured. CodeIgniter's custom SessionHandlerInterface
is used to open, read, and write session data after session_start()
is called.
Maybe this apparent functionality can be used to solve your problems. In case I wasn't clear earlier - use at your own risk!
answered Nov 27 '18 at 2:41
DFriendDFriend
6,9771520
6,9771520
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to putsession_write_close()
, unless I experiment withsession_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!
– sharf
Nov 27 '18 at 14:08
add a comment |
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to putsession_write_close()
, unless I experiment withsession_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!
– sharf
Nov 27 '18 at 14:08
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to put
session_write_close()
, unless I experiment with session_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!– sharf
Nov 27 '18 at 14:08
Unfortunately this is legacy software that was never written with session locking in mind. Script A calls Script B which has session writes, but Script A also calls Script C after B which has more writes, and Script D calls Script C by itself, and Script A can be called by itself or as apart of Script E. So there's no good place to put
session_write_close()
, unless I experiment with session_start()
. As it's being phased out, spending the time on rewriting it correctly is likely not on the table. Thanks!– sharf
Nov 27 '18 at 14:08
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53483367%2fcodeigniter-3-upgrade-session-lock-causing-issues%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown