-C Simplify\sthe\smodePush()/modePop()\simplementation\sin\sthe\sCLI.
-D 2026-04-25T15:05:46.435
+C In\sthe\sCLI,\seliminate\sthe\s2-second\sdelay\sbefore\sgetting\sthe\sprompt\sback\nafter\srunning\sa\s".www"\sor\s".excel".\s\sInstead,\sremember\sthe\sname\sof\sthe\ntemporary\sfile\sthat\sis\sto\sbe\sdeleted\sand\sdelete\sit\slater.
+D 2026-04-25T16:17:23.297
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/resolve.c 928ff887f2a7c64275182060d94d06fdddbe32226c569781cf7e7edc6f58d7fd
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 4c05cde130f26991b7411d8c6809e0630625e18078742c963a047b4b9cc01d49
-F src/shell.c.in 70879f02b889444ec68d9711d4cf62f47c02f95a9bdbfe08cf47a6493ebdc692
+F src/shell.c.in 0c22dd2c11ff87d4904d990dba632940102012d55a9d221940958ad6afe09506
F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 11cfbae735669776c967522294b1606af90b4bd5379e2e1ed722520887b57757
-R ce7f4db60dba8b68ab7b6539006ae917
+P 92cad2cd7284d3a969b713336865007da2b0b2a8eef367d4185802174cbd027a
+R d17ad9dd57a963733572b44ccb3c359d
U drh
-Z 8bf3c788d3ebdc6dce6b0a5a48919414
+Z 936ee9dc91c7afce31c375f047aeb7da
# Remove this line to create a well-formed Fossil manifest.
#define MFLG_CRLF 0x02 /* Use CR/LF output line endings */
#define MFLG_HDR 0x04 /* .header used to change headers on/off */
+/* A file that needs to be deleted, but only after a delay.
+*/
+typedef struct Unlink {
+ sqlite3_int64 tm; /* Unlink after this time */
+ char *zFN; /* Name of file. Space from sqlite3_malloc() */
+} Unlink;
+
/*
** State information about the database connection is contained in an
** instance of the following structure.
Mode mode; /* Current display mode */
Mode *aModeStack; /* Backups */
unsigned nModeStack; /* Number of entries in aModeStack[] */
+ unsigned nUnlink; /* Number of entries in aDelayUnlink[] */
+ Unlink *aUnlink; /* Temp files to unlink after a delay */
struct SavedMode { /* Ability to define custom mode configurations */
char *zTag; /* Name of this saved mode */
Mode mode; /* The saved mode */
/* Give the start/open/xdg-open command some time to get
** going before we continue and potentially delete the
** p->zTempFile data file out from under it */
- sqlite3_sleep(2000);
+ p->aUnlink = realloc(p->aUnlink, sizeof(Unlink)*(1+p->nUnlink));
+ shell_check_oom(p->aUnlink);
+ p->aUnlink[p->nUnlink].tm = timeOfDay()+10000;
+ p->aUnlink[p->nUnlink].zFN = p->zTempFile;
+ p->nUnlink++;
+ p->zTempFile = 0;
}
sqlite3_free(zCmd);
modePop(p);
/*
** Delete a file.
+**
+** If unsuccessful on the first attempt and if pRetry!=NULL and pRetry[0]
+** is positive, then delay for pRetry[0] milliseconds and try again. On
+** a retry, pRetry[0] is set to zero.
+**
+** Return 0 on success and non-zero if unable.
*/
-int shellDeleteFile(const char *zFilename){
+int shellDeleteFile(const char *zFilename, int *pRetry){
int rc;
+ for(;;){
#ifdef _WIN32
- wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
- rc = _wunlink(z);
- sqlite3_free(z);
+ wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
+ rc = _wunlink(z);
+ sqlite3_free(z);
#else
- rc = unlink(zFilename);
+ rc = unlink(zFilename);
#endif
+ if( rc && pRetry && pRetry[0] ){
+ sqlite3_sleep(pRetry[0]);
+ pRetry[0] = 0;
+ continue;
+ }
+ break;
+ }
return rc;
}
/*
-** Try to delete the temporary file (if there is one) and free the
-** memory used to hold the name of the temp file.
+** Try to delete the temporary file (if there is one) with the name
+** p->zTempFile and free the memory used to hold the name of the temp file.
+** If there are any entries in p->aUnlink[] that are old enough, then
+** delete those too, also reclaiming memory.
+**
+** If retry is non-zero and a deletion attempt is not successful,
+** wait for retry milliseconds and try again before giving up.
+** When retry is non-zero, memory is always reclaimed even if the
+** file deletion attempt fails.
+**
+** If bForce is true, deletion is attempted on p->aUnlink[] files
+** even time has not expired.
+**
+** When retry is zero and the deletion attempt fails,
+** memory is not reclaimed.
*/
-static void clearTempFile(ShellState *p){
- if( p->zTempFile==0 ) return;
- if( p->doXdgOpen ) return;
- if( shellDeleteFile(p->zTempFile) ) return;
- sqlite3_free(p->zTempFile);
- p->zTempFile = 0;
+static void clearTempFile(ShellState *p, int retry, int bForce){
+ int alwaysFree = retry>0;
+ int rc = 0;
+ if( p->zTempFile && !p->doXdgOpen ){
+ rc = shellDeleteFile(p->zTempFile, &retry);
+ if( rc==0 || alwaysFree ){
+ sqlite3_free(p->zTempFile);
+ p->zTempFile = 0;
+ }
+ }
+ if( p->nUnlink ){
+ unsigned int i;
+ for(i=0; i<p->nUnlink; i++){
+ if( p->aUnlink[i].tm<timeOfDay()
+ || (bForce && alwaysFree && sqlite3_sleep(retry)>=0)
+ ){
+ char *zFN = p->aUnlink[i].zFN;
+ rc = shellDeleteFile(zFN, &retry);
+ if( rc==0 || alwaysFree ){
+ sqlite3_free(p->aUnlink[i].zFN);
+ p->nUnlink--;
+ if( i<p->nUnlink ){
+ p->aUnlink[i] = p->aUnlink[p->nUnlink];
+ memset(&p->aUnlink[p->nUnlink], 0, sizeof(Unlink));
+ }
+ i--;
+ }
+ }
+ }
+ if( p->nUnlink==0 ){
+ free(p->aUnlink);
+ p->aUnlink = 0;
+ }
+ }
}
/* Forward reference */
r /= 36;
}
zRand[i] = 0;
- clearTempFile(p);
+ clearTempFile(p,1000,0);
sqlite3_free(p->zTempFile);
p->zTempFile = 0;
zHome = find_home_dir(0);
if( nArg==0 ) return 0; /* no tokens, no error */
n = strlen30(azArg[0]);
c = azArg[0][0];
- clearTempFile(p);
+ clearTempFile(p,0,0);
#ifndef SQLITE_OMIT_AUTHORIZATION
if( c=='a' && cli_strncmp(azArg[0], "auth", n)==0 ){
if( cli_strncmp(zFN,"file:",5)==0 ){
char *zDel = shellFilenameFromUri(zFN);
shell_check_oom(zDel);
- shellDeleteFile(zDel);
+ shellDeleteFile(zDel, 0);
sqlite3_free(zDel);
}else{
- shellDeleteFile(zFN);
+ shellDeleteFile(zFN, 0);
}
}
#ifndef SQLITE_SHELL_FIDDLE
output_reset(p);
p->nPopOutput = 0;
}else{
- clearTempFile(p);
+ clearTempFile(p,0,0);
}
if( p->nPopMode ){
modePop(p);
output_reset(&data);
data.nPopOutput = 0;
}else{
- clearTempFile(&data);
+ clearTempFile(&data,0,0);
}
}
}else{
find_home_dir(1);
output_reset(&data);
data.doXdgOpen = 0;
- clearTempFile(&data);
+ clearTempFile(&data,1000,1);
while( data.nModeStack ) modePop(&data);
free(data.aModeStack);
modeFree(&data.mode);