Codeigniter 3 upgrade session lock causing issues












1















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.










share|improve this question



























    1















    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.










    share|improve this question

























      1












      1








      1








      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.










      share|improve this question














      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






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 26 '18 at 14:34









      sharfsharf

      1,39721131




      1,39721131
























          1 Answer
          1






          active

          oldest

          votes


















          1














          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!






          share|improve this answer
























          • 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











          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
          });


          }
          });














          draft saved

          draft discarded


















          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









          1














          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!






          share|improve this answer
























          • 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
















          1














          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!






          share|improve this answer
























          • 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














          1












          1








          1







          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!






          share|improve this answer













          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!







          share|improve this answer












          share|improve this answer



          share|improve this answer










          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 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

















          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




















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

          Calculate evaluation metrics using cross_val_predict sklearn

          Insert data from modal to MySQL (multiple modal on website)