Index: src/bundle.c ================================================================== --- src/bundle.c +++ src/bundle.c @@ -60,11 +60,11 @@ if( !doInit && file_size(zFile, ExtFILE)<0 ){ fossil_fatal("no such file: %s", zFile); } assert( g.db ); zSql = sqlite3_mprintf("ATTACH %Q AS %Q", zFile, zBName); - if( zSql==0 ) fossil_panic("out of memory"); + if( zSql==0 ) fossil_fatal("out of memory"); rc = sqlite3_exec(g.db, zSql, 0, 0, &zErrMsg); sqlite3_free(zSql); if( rc!=SQLITE_OK || zErrMsg ){ if( zErrMsg==0 ) zErrMsg = (char*)sqlite3_errmsg(g.db); fossil_fatal("not a valid bundle: %s", zFile); @@ -73,18 +73,18 @@ db_multi_exec(zBundleInit /*works-like:"%w%w"*/, zBName, zBName); }else{ sqlite3_stmt *pStmt; zSql = sqlite3_mprintf("SELECT bcname, bcvalue" " FROM \"%w\".bconfig", zBName); - if( zSql==0 ) fossil_panic("out of memory"); + if( zSql==0 ) fossil_fatal("out of memory"); rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0); if( rc ) fossil_fatal("not a valid bundle: %s", zFile); sqlite3_free(zSql); sqlite3_finalize(pStmt); zSql = sqlite3_mprintf("SELECT blobid, uuid, sz, delta, notes, data" " FROM \"%w\".bblob", zBName); - if( zSql==0 ) fossil_panic("out of memory"); + if( zSql==0 ) fossil_fatal("out of memory"); rc = sqlite3_prepare(g.db, zSql, -1, &pStmt, 0); if( rc ) fossil_fatal("not a valid bundle: %s", zFile); sqlite3_free(zSql); sqlite3_finalize(pStmt); } Index: src/cgi.c ================================================================== --- src/cgi.c +++ src/cgi.c @@ -1836,11 +1836,11 @@ if( nCycles==0 ){ cgi_setenv("REMOTE_ADDR", zIpAddr); g.zIpAddr = fossil_strdup(zIpAddr); } }else{ - fossil_panic("missing SSH IP address"); + fossil_fatal("missing SSH IP address"); } if( fgets(zLine, sizeof(zLine),g.httpIn)==0 ){ malformed_request("missing HTTP header"); } cgi_trace(zLine); Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -456,16 +456,16 @@ } db.protectMask = db.aProtect[--db.nProtect]; } /* -** Verify that the desired database write pertections are in place. +** Verify that the desired database write protections are in place. ** Throw a fatal error if not. */ void db_assert_protected(unsigned flags){ if( (flags & db.protectMask)!=flags ){ - fossil_panic("missing database write protection bits: %02x", + fossil_fatal("missing database write protection bits: %02x", flags & ~db.protectMask); } } /* @@ -1834,11 +1834,11 @@ /* The HOME variable is required in order to continue. */ if( zHome==0 ){ if( isOptional ) return 0; - fossil_panic("cannot locate home directory - please set one of the " + fossil_fatal("cannot locate home directory - please set one of the " "FOSSIL_HOME, XDG_CONFIG_HOME, or HOME environment " "variables"); } /* Step 4: If $HOME/.config is a directory -> $HOME/.config/fossil.db @@ -1884,17 +1884,17 @@ } rc = file_access(zHome, W_OK); fossil_free(zHome); if( rc ){ if( isOptional ) return 0; - fossil_panic("home directory \"%s\" must be writeable", zHome); + fossil_fatal("home directory \"%s\" must be writeable", zHome); } db_init_database(zDbName, zConfigSchema, (char*)0); } if( file_access(zDbName, W_OK) ){ if( isOptional ) return 0; - fossil_panic("configuration file %s must be writeable", zDbName); + fossil_fatal("configuration file %s must be writeable", zDbName); } if( useAttach ){ db_open_or_attach(zDbName, "configdb"); g.dbConfig = 0; }else{ Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -386,14 +386,14 @@ ** and return non-zero. If everything is ok, return zero. */ int file_unsafe_in_tree_path(const char *zFile){ int n; if( !file_is_absolute_path(zFile) ){ - fossil_panic("%s is not an absolute pathname",zFile); + fossil_fatal("%s is not an absolute pathname",zFile); } if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ - fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); + fossil_fatal("%s is not a prefix of %s", g.zLocalRoot, zFile); } n = file_nondir_objects_on_path(g.zLocalRoot, zFile); if( n ){ fossil_warning("cannot write to %s because non-directory object %.*s" " is in the way", zFile, n, zFile); @@ -1148,13 +1148,13 @@ #ifdef _WIN32 win32_getcwd(zBuf, nBuf); #else if( getcwd(zBuf, nBuf-1)==0 ){ if( errno==ERANGE ){ - fossil_panic("pwd too big: max %d", nBuf-1); + fossil_fatal("pwd too big: max %d", nBuf-1); }else{ - fossil_panic("cannot find current working directory; %s", + fossil_fatal("cannot find current working directory; %s", strerror(errno)); } } #endif return zBuf==zTemp ? fossil_strdup(zBuf) : zBuf; @@ -1823,11 +1823,11 @@ nBasis = 6; zBasis = "fossil"; } do{ blob_zero(pBuf); - if( cnt++>20 ) fossil_panic("cannot generate a temporary filename"); + if( cnt++>20 ) fossil_fatal("cannot generate a temporary filename"); if( zTag==0 ){ sqlite3_randomness(15, zRand); for(i=0; i<15; i++){ zRand[i] = (char)zChars[ ((unsigned char)zRand[i])%(sizeof(zChars)-1) ]; } Index: src/http_ssl.c ================================================================== --- src/http_ssl.c +++ src/http_ssl.c @@ -116,11 +116,11 @@ X509_STORE_set_default_paths(SSL_CTX_get_cert_store(sslCtx)); }else{ /* User has specified a CA location, make sure it exists and use it */ switch( file_isdir(zCaSetting, ExtFILE) ){ case 0: { /* doesn't exist */ - fossil_panic("ssl-ca-location is set to '%s', " + fossil_fatal("ssl-ca-location is set to '%s', " "but is not a file or directory", zCaSetting); break; } case 1: { /* directory */ zCaDirectory = zCaSetting; @@ -130,11 +130,11 @@ zCaFile = zCaSetting; break; } } if( SSL_CTX_load_verify_locations(sslCtx, zCaFile, zCaDirectory)==0 ){ - fossil_panic("Failed to use CA root certificates from " + fossil_fatal("Failed to use CA root certificates from " "ssl-ca-location '%s'", zCaSetting); } } /* Load client SSL identity, preferring the filename specified on the @@ -146,11 +146,11 @@ } if( identityFile!=0 && identityFile[0]!='\0' ){ if( SSL_CTX_use_certificate_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1 || SSL_CTX_use_PrivateKey_file(sslCtx,identityFile,SSL_FILETYPE_PEM)!=1 ){ - fossil_panic("Could not load SSL identity from %s", identityFile); + fossil_fatal("Could not load SSL identity from %s", identityFile); } } /* Register a callback to tell the user what to do when the server asks ** for a cert */ SSL_CTX_set_client_cert_cb(sslCtx, ssl_client_cert_callback); Index: src/http_transport.c ================================================================== --- src/http_transport.c +++ src/http_transport.c @@ -127,19 +127,19 @@ fossil_free(zHost); }else{ blob_append_escaped_arg(&zCmd, pUrlData->name); } if( !is_safe_fossil_command(pUrlData->fossil) ){ - fossil_panic("the ssh:// URL is asking to run an unsafe command [%s] on " + fossil_fatal("the ssh:// URL is asking to run an unsafe command [%s] on " "the server.", pUrlData->fossil); } blob_append_escaped_arg(&zCmd, pUrlData->fossil); blob_append(&zCmd, " test-http", 10); if( pUrlData->path && pUrlData->path[0] ){ blob_append_escaped_arg(&zCmd, pUrlData->path); }else{ - fossil_panic("ssh:// URI does not specify a path to the repository"); + fossil_fatal("ssh:// URI does not specify a path to the repository"); } if( g.fSshTrace ){ fossil_print("%s\n", blob_str(&zCmd)); /* Show the whole SSH command */ } popen2(blob_str(&zCmd), &sshIn, &sshOut, &sshPid, 0); @@ -181,11 +181,11 @@ g.zRepositoryName, iRandId); transport.zInFile = mprintf("%s-%llu-in.http", g.zRepositoryName, iRandId); transport.pFile = fossil_fopen(transport.zOutFile, "wb"); if( transport.pFile==0 ){ - fossil_panic("cannot output temporary file: %s", transport.zOutFile); + fossil_fatal("cannot output temporary file: %s", transport.zOutFile); } transport.isOpen = 1; }else{ rc = socket_open(pUrlData); if( rc==0 ) transport.isOpen = 1; Index: src/import.c ================================================================== --- src/import.c +++ src/import.c @@ -636,11 +636,11 @@ if( gg.nData ){ int got; gg.aData = fossil_malloc( gg.nData+1 ); got = fread(gg.aData, 1, gg.nData, pIn); if( got!=gg.nData ){ - fossil_panic("short read: got %d of %d bytes", got, gg.nData); + fossil_fatal("short read: got %d of %d bytes", got, gg.nData); } gg.aData[got] = '\0'; if( gg.zComment==0 && (gg.xFinish==finish_commit || gg.xFinish==finish_tag) ){ /* Strip trailing newline, it's appended to the comment. */ Index: src/json_status.c ================================================================== --- src/json_status.c +++ src/json_status.c @@ -167,11 +167,11 @@ blob_append(report, zPrefix, nPrefix); blob_appendf(report, "%s %s\n", zLabel, db_column_text(&q, 0)); } db_finalize(&q); if( nErr ){ - fossil_panic("aborting due to prior errors"); + fossil_fatal("aborting due to prior errors"); } #endif return cson_object_value( oPay ); } Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -1468,15 +1468,15 @@ } g.fJail = 1; zRepo = "/"; }else{ for(i=strlen(zDir)-1; i>0 && zDir[i]!='/'; i--){} - if( zDir[i]!='/' ) fossil_panic("bad repository name: %s", zRepo); + if( zDir[i]!='/' ) fossil_fatal("bad repository name: %s", zRepo); if( i>0 ){ zDir[i] = 0; if( file_chdir(zDir, 1) ){ - fossil_panic("unable to chroot into %s", zDir); + fossil_fatal("unable to chroot into %s", zDir); } zDir[i] = '/'; } zRepo = &zDir[i]; } Index: src/printf.c ================================================================== --- src/printf.c +++ src/printf.c @@ -1132,23 +1132,29 @@ return rc; } /* ** Print an error message, rollback all databases, and quit. These -** routines never return. +** routines never return and produce a non-zero process exit status. ** -** The only different between fossil_fatal() and fossil_panic() is that +** The main difference between fossil_fatal() and fossil_panic() is that ** fossil_panic() makes an entry in the error log whereas fossil_fatal() -** does not. If there is not error log, then both routines work the -** same. Hence, the routines are interchangable for commands and only -** make a difference with processing web pages. +** does not. On POSIX platforms, if there is not an error log, then both +** routines work similarly with respect to user-visible effects. Hence, +** the routines are interchangable for commands and only act differently +** when processing web pages. On the Windows platform, fossil_panic() +** also displays a pop-up stating that an error has occured and allowing +** just-in-time debugging to commence. On all platforms, fossil_panic() +** ends execution with a SIGABRT signal, bypassing atexit processing. +** This signal can also produce a core dump on POSIX platforms. ** ** Use fossil_fatal() for malformed inputs that should be reported back ** to the user, but which do not represent a configuration problem or bug. ** ** Use fossil_panic() for any kind of error that should be brought to the -** attention of the system administrator. +** attention of the system administrator or Fossil developers. It should +** be avoided for ordinary usage, parameter, OOM and I/O errors. */ NORETURN void fossil_panic(const char *zFormat, ...){ va_list ap; int rc = 1; char z[1000]; Index: src/sqlcmd.c ================================================================== --- src/sqlcmd.c +++ src/sqlcmd.c @@ -303,11 +303,11 @@ *pnKey = (int)strlen(zKey); }else{ *pnKey = -1; } }else{ - fossil_panic("failed to allocate %u bytes for key", nByte); + fossil_fatal("failed to allocate %u bytes for key", nByte); } } #endif /* Index: src/undo.c ================================================================== --- src/undo.c +++ src/undo.c @@ -269,11 +269,11 @@ ** tree. */ void undo_save(const char *zPathname){ if( undoDisable ) return; if( undo_maybe_save(zPathname, -1)!=UNDO_SAVED_OK ){ - fossil_panic("failed to save undo information for path: %s", + fossil_fatal("failed to save undo information for path: %s", zPathname); } } /* Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -56,25 +56,25 @@ /* ** Malloc and free routines that cannot fail */ void *fossil_malloc(size_t n){ void *p = malloc(n==0 ? 1 : n); - if( p==0 ) fossil_panic("out of memory"); + if( p==0 ) fossil_fatal("out of memory"); return p; } void *fossil_malloc_zero(size_t n){ void *p = malloc(n==0 ? 1 : n); - if( p==0 ) fossil_panic("out of memory"); + if( p==0 ) fossil_fatal("out of memory"); memset(p, 0, n); return p; } void fossil_free(void *p){ free(p); } void *fossil_realloc(void *p, size_t n){ p = realloc(p, n); - if( p==0 ) fossil_panic("out of memory"); + if( p==0 ) fossil_fatal("out of memory"); return p; } void fossil_secure_zero(void *p, size_t n){ volatile unsigned char *vp = (volatile unsigned char *)p; size_t i; @@ -105,22 +105,22 @@ assert( pageSize>0 ); assert( pageSize%2==0 ); #if defined(_WIN32) p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); if( p==NULL ){ - fossil_panic("VirtualAlloc failed: %lu\n", GetLastError()); + fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError()); } if( !VirtualLock(p, pageSize) ){ - fossil_panic("VirtualLock failed: %lu\n", GetLastError()); + fossil_fatal("VirtualLock failed: %lu\n", GetLastError()); } #elif defined(USE_MMAN_H) p = mmap(0, pageSize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if( p==MAP_FAILED ){ - fossil_panic("mmap failed: %d\n", errno); + fossil_fatal("mmap failed: %d\n", errno); } if( mlock(p, pageSize) ){ - fossil_panic("mlock failed: %d\n", errno); + fossil_fatal("mlock failed: %d\n", errno); } #else p = fossil_malloc(pageSize); #endif fossil_secure_zero(p, pageSize); Index: src/winfile.c ================================================================== --- src/winfile.c +++ src/winfile.c @@ -282,11 +282,11 @@ void win32_getcwd(char *zBuf, int nBuf){ int i; char *zUtf8; wchar_t *zWide = fossil_malloc( sizeof(wchar_t)*nBuf ); if( GetCurrentDirectoryW(nBuf, zWide)==0 ){ - fossil_panic("cannot find current working directory."); + fossil_fatal("cannot find current working directory."); } zUtf8 = fossil_path_to_utf8(zWide); fossil_free(zWide); for(i=0; zUtf8[i]; i++) if( zUtf8[i]=='\\' ) zUtf8[i] = '/'; strncpy(zBuf, zUtf8, nBuf); Index: src/winhttp.c ================================================================== --- src/winhttp.c +++ src/winhttp.c @@ -288,11 +288,11 @@ static NORETURN void winhttp_fatal( const char *zOp, const char *zService, const char *zErr ){ - fossil_panic("unable to %s service '%s': %s", zOp, zService, zErr); + fossil_fatal("unable to %s service '%s': %s", zOp, zService, zErr); } /* ** Make sure the server stops as soon as possible after the stopper file ** is found. If there is no stopper file name, do nothing. @@ -604,14 +604,15 @@ } } break; } if( iPort>mxPort ){ + /* These exits are merely fatal because firewall settings can cause them. */ if( mnPort==mxPort ){ - fossil_panic("unable to open listening socket on port %d", mnPort); + fossil_fatal("unable to open listening socket on port %d", mnPort); }else{ - fossil_panic("unable to open listening socket on any" + fossil_fatal("unable to open listening socket on any" " port in the range %d..%d", mnPort, mxPort); } } if( !GetTempPathW(MAX_PATH, zTmpPath) ){ fossil_panic("unable to get path to the temporary directory."); @@ -908,11 +909,11 @@ /* Try to start the control dispatcher thread for the service. */ if( !StartServiceCtrlDispatcherW(ServiceTable) ){ if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ return 1; }else{ - fossil_panic("error from StartServiceCtrlDispatcher()"); + fossil_fatal("error from StartServiceCtrlDispatcher()"); } } return 0; }