From 7c0c460fff751cb77085b0be3db60c336a29f716 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 3 Mar 2010 22:25:18 +0000 Subject: [PATCH] Modify the sqlite3_log() interface and implementation so that it never uses dynamic memory allocation - to avoid deadlocking when called while holding the memory allocator mutex. FossilOrigin-Name: 28d1bc98d60319b10af427072037a0121bc76259 --- manifest | 26 ++++++++++++++++++-------- manifest.uuid | 2 +- src/printf.c | 38 ++++++++++++++++++++++++++------------ src/sqlite.h.in | 6 ++++++ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index ad4a0a60d8..1ad467a64c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,8 @@ -C Fix\ssome\sextra\sinstances\sof\sthe\sconstants\saddressed\sby\s[83e47ca006]. -D 2010-03-03T16:02:06 +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +C Modify\sthe\ssqlite3_log()\sinterface\sand\simplementation\sso\sthat\sit\snever\nuses\sdynamic\smemory\sallocation\s-\sto\savoid\sdeadlocking\swhen\scalled\swhile\nholding\sthe\smemory\sallocator\smutex. +D 2010-03-03T22:25:18 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -160,13 +163,13 @@ F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c 2bb2261190b42a348038f5b1c285c8cef415fcc8 F src/pragma.c 56d95f76154a5f873c32eae485bb625f3c70be46 F src/prepare.c c80630169d82945070a50ebf298611fd9f1485f1 -F src/printf.c aa793722d793520fa31c54d81ddab26b0b410562 +F src/printf.c e2b8c9c8d34583dbda4a09fbcb95c522e8467344 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/resolve.c a1648d98e869937b29f4f697461fe4d60f220a7b F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c 4113ef360430ed4e7533690ef46d06c20204adce F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4 -F src/sqlite.h.in 8793d52e7d4e1124dc3cc94ff56376a97b67965f +F src/sqlite.h.in 08a2d9a278ff0dfd65055a7ec9c599f7ae1a3c18 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqliteInt.h 32e6eb47d2f6fad587e16b0abbbfe3f7d55f2ec0 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 @@ -792,7 +795,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 83e47ca0069de259e98798d84d88301a5b4b6d2e -R b254a895c1aed55531168a2f7a11c1dc -U dan -Z f02550fa435e14ac73a675de6c737016 +P 0354ab279f0ea9915a14d1ed972b4aa6b5a27fd1 +R 926156f9ae585a784895773b700799f0 +U drh +Z a5e3e8dcfa2c5ad6badf36c518ae99a7 +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQFLjuHSoxKgR168RlERAu2uAJ9FMiE/PiQGTF1xE6N9Vhp5wtfQGgCgiZmk +jbyYImM3VWOBm37tm51Ua0M= +=bI8b +-----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index e0189ea52b..2d97de2ba4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0354ab279f0ea9915a14d1ed972b4aa6b5a27fd1 \ No newline at end of file +28d1bc98d60319b10af427072037a0121bc76259 \ No newline at end of file diff --git a/src/printf.c b/src/printf.c index e67d48ee17..a0bae3873b 100644 --- a/src/printf.c +++ b/src/printf.c @@ -939,25 +939,39 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ return z; } +/* +** This is the routine that actually formats the sqlite3_log() message. +** We house it in a separate routine from sqlite3_log() to avoid using +** stack space on small-stack systems when logging is disabled. +** +** sqlite3_log() must render into a static buffer. It cannot dynamically +** allocate memory because it might be called while the memory allocator +** mutex is held. +*/ +static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){ + StrAccum acc; /* String accumulator */ +#ifdef SQLITE_SMALL_STACK + char zMsg[150]; /* Complete log message */ +#else + char zMsg[400]; /* Complete log message */ +#endif + + sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0); + acc.useMalloc = 0; + sqlite3VXPrintf(&acc, 0, zFormat, ap); + sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode, + sqlite3StrAccumFinish(&acc)); +} + /* ** Format and write a message to the log if logging is enabled. */ void sqlite3_log(int iErrCode, const char *zFormat, ...){ - void (*xLog)(void*, int, const char*); /* The global logger function */ - void *pLogArg; /* First argument to the logger */ va_list ap; /* Vararg list */ - char *zMsg; /* Complete log message */ - - xLog = sqlite3GlobalConfig.xLog; - if( xLog ){ + if( sqlite3GlobalConfig.xLog ){ va_start(ap, zFormat); - sqlite3BeginBenignMalloc(); - zMsg = sqlite3_vmprintf(zFormat, ap); - sqlite3EndBenignMalloc(); + renderLogMsg(iErrCode, zFormat, ap); va_end(ap); - pLogArg = sqlite3GlobalConfig.pLogArg; - xLog(pLogArg, iErrCode, zMsg ? zMsg : zFormat); - sqlite3_free(zMsg); } } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index b23cf97782..f831496ab0 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5705,6 +5705,12 @@ int sqlite3_strnicmp(const char *, const char *, int); ** is considered bad form. ** ** The zFormat string must not be NULL. +** +** To avoid deadlocks and other threading problems, the sqlite3_log() routine +** will not use dynamically allocated memory. The log message is stored in +** a fixed-length buffer on the stack. If the log message is longer than +** a few hundred characters, it will be truncated to the length of the +** buffer. */ void sqlite3_log(int iErrCode, const char *zFormat, ...); -- 2.47.3