Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Extra defenses against running the digest alert generator in a context where the transaction will rollback, thus failing to record the new digest time. Change the "fossil server" and "fossil ui" commands to always log errors to the console if no other error logging is defined. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
f87fb02780a03b1d128528ad1fda9bb7 |
User & Date: | drh 2018-06-24 17:44:57.110 |
Context
2018-06-24
| ||
17:51 | Improvements to the /test-warning webpage. ... (check-in: 8d9ad750 user: drh tags: trunk) | |
17:44 | Extra defenses against running the digest alert generator in a context where the transaction will rollback, thus failing to record the new digest time. Change the "fossil server" and "fossil ui" commands to always log errors to the console if no other error logging is defined. ... (check-in: f87fb027 user: drh tags: trunk) | |
16:38 | Enhance the --sqltrace logic. Using those enhancements, locate and fix and unclosed transaction in the email alert sender logic. ... (check-in: f3de8b66 user: drh tags: trunk) | |
Changes
Changes to src/db.c.
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /* ** Arrange for the given file to be deleted on a failure. */ void db_delete_on_failure(const char *zFilename){ assert( db.nDeleteOnFail<count(db.azDeleteOnFail) ); db.azDeleteOnFail[db.nDeleteOnFail++] = fossil_strdup(zFilename); } /* ** This routine is called by the SQLite commit-hook mechanism ** just prior to each commit. All this routine does is verify ** that nBegin really is zero. That insures that transactions ** cannot commit by any means other than by calling db_end_transaction() ** below. | > > > > > > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | /* ** Arrange for the given file to be deleted on a failure. */ void db_delete_on_failure(const char *zFilename){ assert( db.nDeleteOnFail<count(db.azDeleteOnFail) ); db.azDeleteOnFail[db.nDeleteOnFail++] = fossil_strdup(zFilename); } /* ** Return the transaction nesting depth. 0 means we are currently ** not in a transaction. */ int db_transaction_nesting_depth(void){ return db.nBegin; } /* ** This routine is called by the SQLite commit-hook mechanism ** just prior to each commit. All this routine does is verify ** that nBegin really is zero. That insures that transactions ** cannot commit by any means other than by calling db_end_transaction() ** below. |
︙ | ︙ | |||
163 164 165 166 167 168 169 | db.nPriorChanges = sqlite3_total_changes(g.db); db.doRollback = 0; } db.nBegin++; } void db_end_transaction(int rollbackFlag){ if( g.db==0 ) return; | | > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | db.nPriorChanges = sqlite3_total_changes(g.db); db.doRollback = 0; } db.nBegin++; } void db_end_transaction(int rollbackFlag){ if( g.db==0 ) return; if( db.nBegin<=0 ){ fossil_warning("Extra call to db_end_transaction\n"); return; } if( rollbackFlag ){ db.doRollback = 1; if( g.fSqlTrace ) fossil_trace("-- ROLLBACK by request\n"); } db.nBegin--; if( db.nBegin==0 ){ int i; |
︙ | ︙ | |||
1763 1764 1765 1766 1767 1768 1769 | sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0); fprintf(stderr, "-- PCACHE_OVFLOW %10d %10d\n", cur, hiwtr); fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare); } while( db.pAllStmt ){ db_finalize(db.pAllStmt); } | > > | > | | 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 | sqlite3_status(SQLITE_STATUS_PAGECACHE_OVERFLOW, &cur, &hiwtr, 0); fprintf(stderr, "-- PCACHE_OVFLOW %10d %10d\n", cur, hiwtr); fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare); } while( db.pAllStmt ){ db_finalize(db.pAllStmt); } if( db.nBegin ){ fossil_warning("Missed call to db_end_transaction(). Rolling back.\n"); db_end_transaction(1); } pStmt = 0; g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */ sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0); g.dbIgnoreErrors--; db_close_config(); /* If the localdb has a lot of unused free space, ** then VACUUM it as we shut down. */ |
︙ | ︙ |
Changes to src/email.c.
︙ | ︙ | |||
1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 | ** ** This routine is called after certain webpages have been run and ** have already responded. */ void email_auto_exec(void){ int iJulianDay; if( g.db==0 ) return; db_begin_transaction(); if( !email_tables_exist() ) goto autoexec_done; if( !db_get_boolean("email-autoexec",0) ) goto autoexec_done; if( !db_exists("SELECT 1 FROM pending_alert") ) goto autoexec_done; email_send_alerts(0); iJulianDay = db_int(0, "SELECT julianday('now')"); | > > > > < | < | > | < | > | 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 | ** ** This routine is called after certain webpages have been run and ** have already responded. */ void email_auto_exec(void){ int iJulianDay; if( g.db==0 ) return; if( db_transaction_nesting_depth()!=0 ){ fossil_warning("Called email_auto_exec() from within a transaction"); return; } db_begin_transaction(); if( !email_tables_exist() ) goto autoexec_done; if( !db_get_boolean("email-autoexec",0) ) goto autoexec_done; if( !db_exists("SELECT 1 FROM pending_alert") ) goto autoexec_done; email_send_alerts(0); iJulianDay = db_int(0, "SELECT julianday('now')"); if( iJulianDay>db_get_int("email-last-digest",0) ){ if( db_transaction_nesting_depth()!=1 ){ fossil_warning("Transaction nesting error prior to digest processing"); }else{ db_set_int("email-last-digest",iJulianDay,0); email_send_alerts(SENDALERT_DIGEST); } } autoexec_done: db_end_transaction(0); } /* |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 | #endif #if defined(_WIN32) const char *zStopperFile; /* Name of file used to terminate server */ zStopperFile = find_option("stopper", 0, 1); #endif zFileGlob = find_option("files-urlenc",0,1); if( zFileGlob ){ char *z = mprintf("%s", zFileGlob); dehttpize(z); zFileGlob = z; }else{ zFileGlob = find_option("files",0,1); | > > > > | 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 | #endif #if defined(_WIN32) const char *zStopperFile; /* Name of file used to terminate server */ zStopperFile = find_option("stopper", 0, 1); #endif if( g.zErrlog==0 ){ g.zErrlog = "-"; g.fAnyTrace = 1; } zFileGlob = find_option("files-urlenc",0,1); if( zFileGlob ){ char *z = mprintf("%s", zFileGlob); dehttpize(z); zFileGlob = z; }else{ zFileGlob = find_option("files",0,1); |
︙ | ︙ | |||
2705 2706 2707 2708 2709 2710 2711 | for(j=0; (c = z[j])!=0; j++){ fossil_print("%02x", c); } fossil_print("]\n"); } } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 | for(j=0; (c = z[j])!=0; j++){ fossil_print("%02x", c); } fossil_print("]\n"); } } } /* ** WEBPAGE: test-warning ** ** Test error and warning log operation. This webpage is accessible to ** the administrator only. ** ** case=1 Issue a fossil_warning() while generating the page. ** case=2 Extra db_begin_transaction() ** case=3 Extra db_end_transaction() */ void test_warning_page(void){ int iCase = atoi(PD("case","1")); login_check_credentials(); if( !g.perm.Admin ){ fossil_redirect_home(); return; } style_header("Warning Test Page"); @ <p>This is the test page for case=%d(iCase)</p> @ <ol> @ <li value='1'> Call fossil_warning() if( iCase==1 ){ fossil_warning("Test warning message from /test-warning"); } @ <li value='2'> Call db_begin_transaction() if( iCase==2 ){ db_begin_transaction(); } @ <li value='3'> Call db_end_transaction() if( iCase==3 ){ db_end_transaction(0); } @ </ol> @ <p>End of test</p> style_footer(); } |
Changes to src/printf.c.
︙ | ︙ | |||
990 991 992 993 994 995 996 | const char *z; int i; va_list ap; static const char *const azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT", "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_NAME" }; if( g.zErrlog==0 ) return; | > > > | | > | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 | const char *z; int i; va_list ap; static const char *const azEnv[] = { "HTTP_HOST", "HTTP_USER_AGENT", "PATH_INFO", "QUERY_STRING", "REMOTE_ADDR", "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_NAME" }; if( g.zErrlog==0 ) return; if( g.zErrlog[0]=='-' && g.zErrlog[1]==0 ){ out = stderr; }else{ out = fossil_fopen(g.zErrlog, "a"); if( out==0 ) return; } now = time(0); pNow = gmtime(&now); fprintf(out, "------------- %04d-%02d-%02d %02d:%02d:%02d UTC ------------\n", pNow->tm_year+1900, pNow->tm_mon+1, pNow->tm_mday+1, pNow->tm_hour, pNow->tm_min, pNow->tm_sec); va_start(ap, zFormat); vfprintf(out, zFormat, ap); |
︙ | ︙ |