* [Tarantool-patches] [PATCH v3 0/2] Fix working with VDBE @ 2020-12-16 23:09 Leonid Vasiliev 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c Leonid Vasiliev 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure Leonid Vasiliev 0 siblings, 2 replies; 9+ messages in thread From: Leonid Vasiliev @ 2020-12-16 23:09 UTC (permalink / raw) To: tarantool-patches, v.shpilevoy, imeevma, korablev, sergos https://github.com/tarantool/tarantool/issues/5537 https://github.com/tarantool/tarantool/tree/lvasilev/gh-5537-sql-vdbe-sort-troubles @ChangeLog is absent Changes in v2: - add common diag_set if sql_execute is failure. Changes in v3: - "sql: update temporary file name format" patch has been pushed to master - add missing diag_set on failure to all functions when working inside os_unix.c Leonid Vasiliev (2): sql: add missing diag_set on failure when working inside os_unix.c sql: add panic() call in sql_execute() on complete failure src/box/execute.c | 12 +++++++++- src/box/sql/os_unix.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 6 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c 2020-12-16 23:09 [Tarantool-patches] [PATCH v3 0/2] Fix working with VDBE Leonid Vasiliev @ 2020-12-16 23:09 ` Leonid Vasiliev 2020-12-20 16:02 ` Vladislav Shpilevoy 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure Leonid Vasiliev 1 sibling, 1 reply; 9+ messages in thread From: Leonid Vasiliev @ 2020-12-16 23:09 UTC (permalink / raw) To: tarantool-patches, v.shpilevoy, imeevma, korablev, sergos SQL module didn't set an error in the diagnostics area on failure inside unix.c. This could lead to a crash like in #5537. Co-authored-by: Mergen Imeev<imeevma@gmail.com> Follow-up #5537 --- src/box/sql/os_unix.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c index d64f1bd..4f59767 100644 --- a/src/box/sql/os_unix.c +++ b/src/box/sql/os_unix.c @@ -159,14 +159,17 @@ robust_open(const char *z, int f, mode_t m) if (fd < 0) { if (errno == EINTR) continue; + diag_set(SystemError, "failed to open file '%s'", z); break; } if (fd >= SQL_MINIMUM_FILE_DESCRIPTOR) break; close(fd); fd = -1; - if (open("/dev/null", f, m) < 0) + if (open("/dev/null", f, m) < 0) { + diag_set(SystemError, "failed to open '/dev/null'"); break; + } } if (fd >= 0) { if (m != 0) { @@ -193,6 +196,10 @@ robust_ftruncate(int h, sql_int64 sz) do { rc = ftruncate(h, sz); } while (rc < 0 && errno == EINTR); + + if (rc < 0) + diag_set(SystemError, "failed to truncate file"); + return rc; } @@ -395,6 +402,9 @@ findInodeInfo(unixFile * pFile, /* Unix file with file desc used in the key */ fd = pFile->h; rc = fstat(fd, &statbuf); if (rc != 0) { + diag_set(SystemError, + "failed to retrive information about the file '%s'", + pFile->zPath); storeLastErrno(pFile, errno); return -1; } @@ -433,7 +443,13 @@ static int fileHasMoved(unixFile * pFile) { struct stat buf; - return pFile->pInode != NULL && (stat(pFile->zPath, &buf) != 0 || + int rc = stat(pFile->zPath, &buf); + if (rc < 0) { + diag_set(SystemError, + "failed to retrive information about the file '%s'", + pFile->zPath); + } + return pFile->pInode != NULL && (rc != 0 || (u64) buf.st_ino != pFile->pInode->fileId.ino); } @@ -473,8 +489,12 @@ unixFileLock(unixFile * pFile, struct flock *pLock) lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; rc = fcntl(pFile->h, F_SETLK, &lock); - if (rc < 0) + if (rc < 0) { + diag_set(SystemError, + "failed to acquire a lock on the" + " file '%s'", pFile->zPath); return rc; + } pInode->bProcessLock = 1; pInode->nLock++; } else { @@ -482,6 +502,11 @@ unixFileLock(unixFile * pFile, struct flock *pLock) } } else { rc = fcntl(pFile->h, F_SETLK, pLock); + if (rc < 0) { + diag_set(SystemError, + "failed to acquire a lock on the file '%s'", + pFile->zPath); + } } return rc; } @@ -729,6 +754,9 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) do { newOffset = lseek(id->h, offset, SEEK_SET); if (newOffset < 0) { + diag_set(SystemError, + "failed to reposition the offset of '%s' file", + id->zPath); storeLastErrno((unixFile *) id, errno); return -1; } @@ -740,6 +768,8 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) got = 1; continue; } + diag_set(SystemError, "failed to read from file '%s'", + id->zPath); prior = 0; storeLastErrno((unixFile *) id, errno); break; @@ -825,10 +855,16 @@ seekAndWriteFd(int fd, /* File descriptor to write to */ do { i64 iSeek = lseek(fd, iOff, SEEK_SET); if (iSeek < 0) { + diag_set(SystemError, + "failed to reposition file offset"); rc = -1; break; } rc = write(fd, pBuf, nBuf); + if (rc < 0) { + diag_set(SystemError, + "failed to write %i bytes to file", nBuf); + } } while (rc < 0 && errno == EINTR); if (rc < 0) @@ -940,8 +976,12 @@ fcntlSizeHint(unixFile * pFile, i64 nByte) i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - if (fstat(pFile->h, &buf)) + if (fstat(pFile->h, &buf)) { + diag_set(SystemError, + "failed to retrive information about the" + " file '%s'", pFile->zPath); return -1; + } nSize = ((nByte + pFile->szChunk - @@ -1165,8 +1205,12 @@ unixMapfile(unixFile * pFd, i64 nMap) if (nMap < 0) { struct stat statbuf; /* Low-level file information */ - if (fstat(pFd->h, &statbuf)) + if (fstat(pFd->h, &statbuf)) { + diag_set(SystemError, + "failed to retrive information about the" + " file '%s'", pFd->zPath); return -1; + } nMap = statbuf.st_size; } if (nMap > pFd->mmapSizeMax) { @@ -1449,6 +1493,8 @@ unixTempFileDir(void) break; zDir = azDirs[i++]; } + diag_set(ClientError, ER_SYSTEM, + "No access to any temporary directory"); return 0; } @@ -1558,6 +1604,9 @@ getFileMode(const char *zFile, /* File name */ *pUid = sStat.st_uid; *pGid = sStat.st_gid; } else { + diag_set(SystemError, + "failed to retrive information about the file '%s'", + zFile); rc = -1; } return rc; @@ -1813,6 +1862,7 @@ unixDelete(sql_vfs * NotUsed, /* VFS containing this as the xDelete method */ int rc = 0; UNUSED_PARAMETER(NotUsed); if (unlink(zPath) == (-1)) { + diag_set(SystemError, "failed to unlink the file '%s'", zPath); return -1; } if ((dirSync & 1) != 0) { @@ -1821,6 +1871,9 @@ unixDelete(sql_vfs * NotUsed, /* VFS containing this as the xDelete method */ if (rc == 0) { struct stat buf; if (fstat(fd, &buf)) { + diag_set(SystemError, + "failed to retrive information about" + " the file '%s'", zPath); rc = -1; } close(fd); -- 2.7.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c Leonid Vasiliev @ 2020-12-20 16:02 ` Vladislav Shpilevoy 2020-12-23 23:27 ` Leonid Vasiliev 0 siblings, 1 reply; 9+ messages in thread From: Vladislav Shpilevoy @ 2020-12-20 16:02 UTC (permalink / raw) To: Leonid Vasiliev, tarantool-patches, imeevma, korablev, sergos Hi! Thanks for the patch! On 17.12.2020 00:09, Leonid Vasiliev via Tarantool-patches wrote: > SQL module didn't set an error in the diagnostics area on failure > inside unix.c. This could lead to a crash like in #5537. unix.c -> os_unix.c. I see os_unix.c already has some kind of diagnostics area filled by storeLastErrno(). Did you think about syncing diag_set with this one? See 8 comments below. > src/box/sql/os_unix.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- > 1 file changed, 58 insertions(+), 5 deletions(-) > > diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c > index d64f1bd..4f59767 100644 > --- a/src/box/sql/os_unix.c > +++ b/src/box/sql/os_unix.c> @@ -433,7 +443,13 @@ static int > fileHasMoved(unixFile * pFile) > { > struct stat buf; > - return pFile->pInode != NULL && (stat(pFile->zPath, &buf) != 0 || > + int rc = stat(pFile->zPath, &buf); 1. stat() wasn't called if pInode was NULL. Now it is. Lets not change the behaviour. > + if (rc < 0) { 2. Why do you use < 0 here and != just 5 lines below? But the more important question is why do you even set diag here? This function (fileHasMoved) can't "fail". It just returns true or false - moved or not moved. There is no a way to return an error from it. Any issues with 'stat' were treated as 'file has moved'. I assume it was even the purpose, because usually stat() fails if there is no such file. > + diag_set(SystemError, > + "failed to retrive information about the file '%s'", > + pFile->zPath); > + } > + return pFile->pInode != NULL && (rc != 0 || > (u64) buf.st_ino != > pFile->pInode->fileId.ino); > } > @@ -482,6 +502,11 @@ unixFileLock(unixFile * pFile, struct flock *pLock) > } > } else { > rc = fcntl(pFile->h, F_SETLK, pLock); > + if (rc < 0) { > + diag_set(SystemError, > + "failed to acquire a lock on the file '%s'", > + pFile->zPath); 3. This function is not only about lock acquire. It is also used to remove the lock. For instance, by posixUnlock(). > + } > } > return rc; > } > @@ -740,6 +768,8 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) > got = 1; > continue; > } > + diag_set(SystemError, "failed to read from file '%s'", > + id->zPath); > prior = 0; > storeLastErrno((unixFile *) id, errno); > break; 4. unixRead() returns -1 in case seekAndRead() returned 0. But there is no a diag_set() anywhere for this. > @@ -825,10 +855,16 @@ seekAndWriteFd(int fd, /* File descriptor to write to */ > do { > i64 iSeek = lseek(fd, iOff, SEEK_SET); > if (iSeek < 0) { > + diag_set(SystemError, > + "failed to reposition file offset"); > rc = -1; > break; > } > rc = write(fd, pBuf, nBuf); > + if (rc < 0) { > + diag_set(SystemError, > + "failed to write %i bytes to file", nBuf); 5. The error is supposed to be ignored if errno is EINTR. > + } > } while (rc < 0 && errno == EINTR); > > if (rc < 0) 6. unixWrite() returns -1 if not everything was written, it seems. Here: if (amt > wrote) { if (wrote < 0 && pFile->lastErrno != ENOSPC) { /* lastErrno set by seekAndWrite */ return -1; } else { storeLastErrno(pFile, 0); /* not a system error */ return -1; } } The 'else' branch. But I don't understand how it can happen. > @@ -940,8 +976,12 @@ fcntlSizeHint(unixFile * pFile, i64 nByte) > i64 nSize; /* Required file size */ > struct stat buf; /* Used to hold return values of fstat() */ > > - if (fstat(pFile->h, &buf)) > + if (fstat(pFile->h, &buf)) { 7. I suggest to use != 0 explicitly, according to the code style rules for the new code. The same in the hunk below. > + diag_set(SystemError, > + "failed to retrive information about the" > + " file '%s'", pFile->zPath); > return -1; > + } > > nSize = > ((nByte + pFile->szChunk - > @@ -1165,8 +1205,12 @@ unixMapfile(unixFile * pFd, i64 nMap) > > if (nMap < 0) { > struct stat statbuf; /* Low-level file information */ > - if (fstat(pFd->h, &statbuf)) > + if (fstat(pFd->h, &statbuf)) { > + diag_set(SystemError, > + "failed to retrive information about the" > + " file '%s'", pFd->zPath); > return -1; > + } > nMap = statbuf.st_size; > } > if (nMap > pFd->mmapSizeMax) { > @@ -1449,6 +1493,8 @@ unixTempFileDir(void) > break; > zDir = azDirs[i++]; > } > + diag_set(ClientError, ER_SYSTEM, > + "No access to any temporary directory"); > return 0; > } 8. unixGetTempname() does not set diag in one case of -1 return. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c 2020-12-20 16:02 ` Vladislav Shpilevoy @ 2020-12-23 23:27 ` Leonid Vasiliev 2020-12-24 16:00 ` Vladislav Shpilevoy 0 siblings, 1 reply; 9+ messages in thread From: Leonid Vasiliev @ 2020-12-23 23:27 UTC (permalink / raw) To: Vladislav Shpilevoy, tarantool-patches, imeevma, korablev, sergos Hi! Thank you for the review. The updated patch is at the end of the letter. On 20.12.2020 19:02, Vladislav Shpilevoy wrote: > Hi! Thanks for the patch! > > On 17.12.2020 00:09, Leonid Vasiliev via Tarantool-patches wrote: >> SQL module didn't set an error in the diagnostics area on failure >> inside unix.c. This could lead to a crash like in #5537. > > unix.c -> os_unix.c. Updated. > > I see os_unix.c already has some kind of diagnostics area filled > by storeLastErrno(). Did you think about syncing diag_set with this > one? Yep, right after your question: "Did you think about syncing diag_set with this one?":) As far as I can see, `diag_set()` now has more coverage than `storeLastErrno()`. Seems like some `diag_set` can be moved to `storeLastErrno()`, but will need to add a `message` argument to `storeLastErrno()` for `diag_set ()`. I think such refactoring can be done in a separate ticket if it is useful, because it isn't related with a crash. Do you have other thoughts? > > See 8 comments below. > >> src/box/sql/os_unix.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++---- >> 1 file changed, 58 insertions(+), 5 deletions(-) >> >> diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c >> index d64f1bd..4f59767 100644 >> --- a/src/box/sql/os_unix.c >> +++ b/src/box/sql/os_unix.c> @@ -433,7 +443,13 @@ static int >> fileHasMoved(unixFile * pFile) >> { >> struct stat buf; >> - return pFile->pInode != NULL && (stat(pFile->zPath, &buf) != 0 || >> + int rc = stat(pFile->zPath, &buf); > > 1. stat() wasn't called if pInode was NULL. Now it is. Lets not > change the behaviour. After your second note, this one is deprecated. > >> + if (rc < 0) { > > 2. Why do you use < 0 here and != just 5 lines below? > > But the more important question is why do you even set diag > here? This function (fileHasMoved) can't "fail". It just > returns true or false - moved or not moved. There is no a way > to return an error from it. Any issues with 'stat' were treated > as 'file has moved'. I assume it was even the purpose, because > usually stat() fails if there is no such file. OMG! That's my mistake. Thank you. Changes reverted. > >> + diag_set(SystemError, >> + "failed to retrive information about the file '%s'", >> + pFile->zPath); >> + } >> + return pFile->pInode != NULL && (rc != 0 || >> (u64) buf.st_ino != >> pFile->pInode->fileId.ino); >> } >> @@ -482,6 +502,11 @@ unixFileLock(unixFile * pFile, struct flock *pLock) >> } >> } else { >> rc = fcntl(pFile->h, F_SETLK, pLock); >> + if (rc < 0) { >> + diag_set(SystemError, >> + "failed to acquire a lock on the file '%s'", >> + pFile->zPath); > > 3. This function is not only about lock acquire. It is also used > to remove the lock. For instance, by posixUnlock(). Updated the message. > >> + } >> } >> return rc; >> } >> @@ -740,6 +768,8 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) >> got = 1; >> continue; >> } >> + diag_set(SystemError, "failed to read from file '%s'", >> + id->zPath); >> prior = 0; >> storeLastErrno((unixFile *) id, errno); >> break; > > 4. unixRead() returns -1 in case seekAndRead() returned 0. But > there is no a diag_set() anywhere for this. AFAIU you talking about `else` case. Updated. > >> @@ -825,10 +855,16 @@ seekAndWriteFd(int fd, /* File descriptor to write to */ >> do { >> i64 iSeek = lseek(fd, iOff, SEEK_SET); >> if (iSeek < 0) { >> + diag_set(SystemError, >> + "failed to reposition file offset"); >> rc = -1; >> break; >> } >> rc = write(fd, pBuf, nBuf); >> + if (rc < 0) { >> + diag_set(SystemError, >> + "failed to write %i bytes to file", nBuf); > > 5. The error is supposed to be ignored if errno is EINTR. Yep. It's true. > >> + } >> } while (rc < 0 && errno == EINTR); >> >> if (rc < 0) > > 6. unixWrite() returns -1 if not everything was written, it > seems. Here: > > if (amt > wrote) { > if (wrote < 0 && pFile->lastErrno != ENOSPC) { > /* lastErrno set by seekAndWrite */ > return -1; > } else { > storeLastErrno(pFile, 0); /* not a system error */ > return -1; > } > } > > The 'else' branch. But I don't understand how it can happen. Updated. > >> @@ -940,8 +976,12 @@ fcntlSizeHint(unixFile * pFile, i64 nByte) >> i64 nSize; /* Required file size */ >> struct stat buf; /* Used to hold return values of fstat() */ >> >> - if (fstat(pFile->h, &buf)) >> + if (fstat(pFile->h, &buf)) { > > 7. I suggest to use != 0 explicitly, according to the code > style rules for the new code. The same in the hunk below. Ok. I don't mind. > >> + diag_set(SystemError, >> + "failed to retrive information about the" >> + " file '%s'", pFile->zPath); >> return -1; >> + } >> >> nSize = >> ((nByte + pFile->szChunk - >> @@ -1165,8 +1205,12 @@ unixMapfile(unixFile * pFd, i64 nMap) >> >> if (nMap < 0) { >> struct stat statbuf; /* Low-level file information */ >> - if (fstat(pFd->h, &statbuf)) >> + if (fstat(pFd->h, &statbuf)) { >> + diag_set(SystemError, >> + "failed to retrive information about the" >> + " file '%s'", pFd->zPath); >> return -1; >> + } >> nMap = statbuf.st_size; >> } >> if (nMap > pFd->mmapSizeMax) { >> @@ -1449,6 +1493,8 @@ unixTempFileDir(void) >> break; >> zDir = azDirs[i++]; >> } >> + diag_set(ClientError, ER_SYSTEM, >> + "No access to any temporary directory"); >> return 0; >> } > > 8. unixGetTempname() does not set diag in one case of -1 return. Updated. > Updated patch: SQL module didn't set an error in the diagnostics area on failure inside os_unix.c. This could lead to a crash like in #5537. Co-authored-by: Mergen Imeev<imeevma@gmail.com> Follow-up #5537 --- src/box/sql/os_unix.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c index d64f1bd..07461f5 100644 --- a/src/box/sql/os_unix.c +++ b/src/box/sql/os_unix.c @@ -159,14 +159,17 @@ robust_open(const char *z, int f, mode_t m) if (fd < 0) { if (errno == EINTR) continue; + diag_set(SystemError, "failed to open file '%s'", z); break; } if (fd >= SQL_MINIMUM_FILE_DESCRIPTOR) break; close(fd); fd = -1; - if (open("/dev/null", f, m) < 0) + if (open("/dev/null", f, m) < 0) { + diag_set(SystemError, "failed to open '/dev/null'"); break; + } } if (fd >= 0) { if (m != 0) { @@ -193,6 +196,10 @@ robust_ftruncate(int h, sql_int64 sz) do { rc = ftruncate(h, sz); } while (rc < 0 && errno == EINTR); + + if (rc < 0) + diag_set(SystemError, "failed to truncate file"); + return rc; } @@ -395,6 +402,9 @@ findInodeInfo(unixFile * pFile, /* Unix file with file desc used in the key */ fd = pFile->h; rc = fstat(fd, &statbuf); if (rc != 0) { + diag_set(SystemError, + "failed to retrieve information about the file '%s'", + pFile->zPath); storeLastErrno(pFile, errno); return -1; } @@ -473,8 +483,12 @@ unixFileLock(unixFile * pFile, struct flock *pLock) lock.l_len = SHARED_SIZE; lock.l_type = F_WRLCK; rc = fcntl(pFile->h, F_SETLK, &lock); - if (rc < 0) + if (rc < 0) { + diag_set(SystemError, + "failed to acquire / release a lock on" + " the file '%s'", pFile->zPath); return rc; + } pInode->bProcessLock = 1; pInode->nLock++; } else { @@ -482,6 +496,11 @@ unixFileLock(unixFile * pFile, struct flock *pLock) } } else { rc = fcntl(pFile->h, F_SETLK, pLock); + if (rc < 0) { + diag_set(SystemError, + "failed to acquire / release a lock on" + " the file '%s'", pFile->zPath); + } } return rc; } @@ -729,6 +748,9 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) do { newOffset = lseek(id->h, offset, SEEK_SET); if (newOffset < 0) { + diag_set(SystemError, + "failed to reposition the offset of '%s' file", + id->zPath); storeLastErrno((unixFile *) id, errno); return -1; } @@ -740,6 +762,8 @@ seekAndRead(unixFile * id, sql_int64 offset, void *pBuf, int cnt) got = 1; continue; } + diag_set(SystemError, "failed to read from file '%s'", + id->zPath); prior = 0; storeLastErrno((unixFile *) id, errno); break; @@ -794,6 +818,11 @@ unixRead(sql_file * id, void *pBuf, int amt, sql_int64 offset) /* lastErrno set by seekAndRead */ return -1; } else { + /* Read less than planned from file. */ + const char *err = tt_sprintf("read less (%i bytes) than " + "planned (%i bytes) from file: %s", + got, amt, pFile->zPath); + diag_set(ClientError, ER_SQL_EXECUTE, err); storeLastErrno(pFile, 0); /* not a system error */ /* Unread parts of the buffer must be zero-filled */ memset(&((char *)pBuf)[got], 0, amt - got); @@ -825,10 +854,16 @@ seekAndWriteFd(int fd, /* File descriptor to write to */ do { i64 iSeek = lseek(fd, iOff, SEEK_SET); if (iSeek < 0) { + diag_set(SystemError, + "failed to reposition file offset"); rc = -1; break; } rc = write(fd, pBuf, nBuf); + if (rc < 0 && errno != EINTR) { + diag_set(SystemError, + "failed to write %i bytes to file", nBuf); + } } while (rc < 0 && errno == EINTR); if (rc < 0) @@ -873,6 +908,12 @@ unixWrite(sql_file * id, const void *pBuf, int amt, sql_int64 offset) /* lastErrno set by seekAndWrite */ return -1; } else { + /* Wrote to file less than planned. */ + const char *err = tt_sprintf("wrote less (%i bytes) " + "than planned (%i bytes) " + "to file: %s", + wrote, amt, pFile->zPath); + diag_set(ClientError, ER_SQL_EXECUTE, err); storeLastErrno(pFile, 0); /* not a system error */ return -1; } @@ -940,8 +981,12 @@ fcntlSizeHint(unixFile * pFile, i64 nByte) i64 nSize; /* Required file size */ struct stat buf; /* Used to hold return values of fstat() */ - if (fstat(pFile->h, &buf)) + if (fstat(pFile->h, &buf) != 0) { + diag_set(SystemError, + "failed to retrieve information about the" + " file '%s'", pFile->zPath); return -1; + } nSize = ((nByte + pFile->szChunk - @@ -1165,8 +1210,12 @@ unixMapfile(unixFile * pFd, i64 nMap) if (nMap < 0) { struct stat statbuf; /* Low-level file information */ - if (fstat(pFd->h, &statbuf)) + if (fstat(pFd->h, &statbuf) != 0) { + diag_set(SystemError, + "failed to retrieve information about the" + " file '%s'", pFd->zPath); return -1; + } nMap = statbuf.st_size; } if (nMap > pFd->mmapSizeMax) { @@ -1449,6 +1498,8 @@ unixTempFileDir(void) break; zDir = azDirs[i++]; } + diag_set(ClientError, ER_SYSTEM, + "No access to any temporary directory"); return 0; } @@ -1480,8 +1531,11 @@ unixGetTempname(int nBuf, char *zBuf) sql_snprintf(nBuf, zBuf, "%s/" SQL_TEMP_FILE_PREFIX "%ld_%llx%c", zDir, (long)randomnessPid, r, 0); - if (zBuf[nBuf - 2] != 0 || (iLimit++) > 10) + if (zBuf[nBuf - 2] != 0 || (iLimit++) > 10) { + diag_set(ClientError, ER_SQL_EXECUTE, + "can't create temporary file"); return -1; + } } while (access(zBuf, 0) == 0); return 0; } @@ -1558,6 +1612,9 @@ getFileMode(const char *zFile, /* File name */ *pUid = sStat.st_uid; *pGid = sStat.st_gid; } else { + diag_set(SystemError, + "failed to retrieve information about the file '%s'", + zFile); rc = -1; } return rc; @@ -1813,6 +1870,7 @@ unixDelete(sql_vfs * NotUsed, /* VFS containing this as the xDelete method */ int rc = 0; UNUSED_PARAMETER(NotUsed); if (unlink(zPath) == (-1)) { + diag_set(SystemError, "failed to unlink the file '%s'", zPath); return -1; } if ((dirSync & 1) != 0) { @@ -1820,7 +1878,10 @@ unixDelete(sql_vfs * NotUsed, /* VFS containing this as the xDelete method */ rc = openDirectory(zPath, &fd); if (rc == 0) { struct stat buf; - if (fstat(fd, &buf)) { + if (fstat(fd, &buf) != 0) { + diag_set(SystemError, + "failed to retrieve information about" + " the file '%s'", zPath); rc = -1; } close(fd); -- 2.7.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c 2020-12-23 23:27 ` Leonid Vasiliev @ 2020-12-24 16:00 ` Vladislav Shpilevoy 2020-12-24 16:59 ` Nikita Pettik 0 siblings, 1 reply; 9+ messages in thread From: Vladislav Shpilevoy @ 2020-12-24 16:00 UTC (permalink / raw) To: Leonid Vasiliev, tarantool-patches, imeevma, korablev, sergos Hi! Thanks for the fixes! See 1 comment below. After that the patchset will LGTM, and you can send it to Nikita on a second review. > diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c > index d64f1bd..07461f5 100644 > --- a/src/box/sql/os_unix.c > +++ b/src/box/sql/os_unix.c > @@ -873,6 +908,12 @@ unixWrite(sql_file * id, const void *pBuf, int amt, sql_int64 offset) > /* lastErrno set by seekAndWrite */ > return -1; > } else { > + /* Wrote to file less than planned. */ > + const char *err = tt_sprintf("wrote less (%i bytes) " > + "than planned (%i bytes) " > + "to file: %s", > + wrote, amt, pFile->zPath); > + diag_set(ClientError, ER_SQL_EXECUTE, err); Planned wasn't amt, because amt is modified in the loop above. Also 'wrote' will be -1 here, because this branch is taked on ENOSPC and write() returned -1. Perpahs it is enough to say that didn't have enough space to write 'amt' bytes (this is how much was left to write). > storeLastErrno(pFile, 0); /* not a system error */ > return -1; > } ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c 2020-12-24 16:00 ` Vladislav Shpilevoy @ 2020-12-24 16:59 ` Nikita Pettik 0 siblings, 0 replies; 9+ messages in thread From: Nikita Pettik @ 2020-12-24 16:59 UTC (permalink / raw) To: Vladislav Shpilevoy; +Cc: tarantool-patches On 24 Dec 17:00, Vladislav Shpilevoy wrote: > Hi! Thanks for the fixes! > > See 1 comment below. After that the patchset will LGTM, and > you can send it to Nikita on a second review. Right away I can say that it would be super nice to see corresponding test (using error injections I gueess). Otherwise we can't say for sure that all this stubs are working... > > diff --git a/src/box/sql/os_unix.c b/src/box/sql/os_unix.c > > index d64f1bd..07461f5 100644 > > --- a/src/box/sql/os_unix.c > > +++ b/src/box/sql/os_unix.c > > @@ -873,6 +908,12 @@ unixWrite(sql_file * id, const void *pBuf, int amt, sql_int64 offset) > > /* lastErrno set by seekAndWrite */ > > return -1; > > } else { > > + /* Wrote to file less than planned. */ > > + const char *err = tt_sprintf("wrote less (%i bytes) " > > + "than planned (%i bytes) " > > + "to file: %s", > > + wrote, amt, pFile->zPath); > > + diag_set(ClientError, ER_SQL_EXECUTE, err); > > Planned wasn't amt, because amt is modified in the loop above. Also > 'wrote' will be -1 here, because this branch is taked on ENOSPC and > write() returned -1. > > Perpahs it is enough to say that didn't have enough space to write > 'amt' bytes (this is how much was left to write). > > > storeLastErrno(pFile, 0); /* not a system error */ > > return -1; > > } ^ permalink raw reply [flat|nested] 9+ messages in thread
* [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure 2020-12-16 23:09 [Tarantool-patches] [PATCH v3 0/2] Fix working with VDBE Leonid Vasiliev 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c Leonid Vasiliev @ 2020-12-16 23:09 ` Leonid Vasiliev 2020-12-20 16:02 ` Vladislav Shpilevoy 1 sibling, 1 reply; 9+ messages in thread From: Leonid Vasiliev @ 2020-12-16 23:09 UTC (permalink / raw) To: tarantool-patches, v.shpilevoy, imeevma, korablev, sergos In SQL, on failure sometimes an error sets to the diag, sometimes not. And this can dived to situation as in #5537(SEGFAULT). So, let's call `panic()` in that case, because something is very wrong, and it is not safe to continue execution. Follow-up #5537 --- src/box/execute.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/box/execute.c b/src/box/execute.c index e14da20..a424349 100644 --- a/src/box/execute.c +++ b/src/box/execute.c @@ -687,8 +687,18 @@ sql_execute(struct sql_stmt *stmt, struct port *port, struct region *region) rc = sql_step(stmt); assert(rc != SQL_ROW && rc != 0); } - if (rc != SQL_DONE) + if (rc != SQL_DONE) { + /* + * In SQL, on failure sometimes an error sets to the diag, + * sometimes not. So, let's call `panic()` in that case, because + * something is very wrong, and it is not safe to continue + * execution. + */ + if (diag_is_empty(diag_get())) + panic("failed to execute SQL statement"); + return -1; + } return 0; } -- 2.7.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure Leonid Vasiliev @ 2020-12-20 16:02 ` Vladislav Shpilevoy 2020-12-23 22:38 ` Leonid Vasiliev 0 siblings, 1 reply; 9+ messages in thread From: Vladislav Shpilevoy @ 2020-12-20 16:02 UTC (permalink / raw) To: Leonid Vasiliev, tarantool-patches, imeevma, korablev, sergos Thanks for the patch! On 17.12.2020 00:09, Leonid Vasiliev via Tarantool-patches wrote: > In SQL, on failure sometimes an error sets to the diag, sometimes not. > And this can dived to situation as in #5537(SEGFAULT). dived -> lead. > So, let's call `panic()` in that case, because something is very wrong, > and it is not safe to continue execution. > > Follow-up #5537 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure 2020-12-20 16:02 ` Vladislav Shpilevoy @ 2020-12-23 22:38 ` Leonid Vasiliev 0 siblings, 0 replies; 9+ messages in thread From: Leonid Vasiliev @ 2020-12-23 22:38 UTC (permalink / raw) To: Vladislav Shpilevoy, tarantool-patches, imeevma, korablev, sergos Hi! Thank you for the review. On 20.12.2020 19:02, Vladislav Shpilevoy wrote: > Thanks for the patch! > > On 17.12.2020 00:09, Leonid Vasiliev via Tarantool-patches wrote: >> In SQL, on failure sometimes an error sets to the diag, sometimes not. >> And this can dived to situation as in #5537(SEGFAULT). > > dived -> lead. > >> So, let's call `panic()` in that case, because something is very wrong, >> and it is not safe to continue execution. >> >> Follow-up #5537 Updated: In SQL, on failure sometimes an error sets to the diag, sometimes not. And this can lead to situation as in #5537(SEGFAULT). So, let's call `panic()` in that case, because something is very wrong, and it is not safe to continue execution. Follow-up #5537 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2020-12-24 16:59 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-12-16 23:09 [Tarantool-patches] [PATCH v3 0/2] Fix working with VDBE Leonid Vasiliev 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 1/2] sql: add missing diag_set on failure when working inside os_unix.c Leonid Vasiliev 2020-12-20 16:02 ` Vladislav Shpilevoy 2020-12-23 23:27 ` Leonid Vasiliev 2020-12-24 16:00 ` Vladislav Shpilevoy 2020-12-24 16:59 ` Nikita Pettik 2020-12-16 23:09 ` [Tarantool-patches] [PATCH v3 2/2] sql: add panic() call in sql_execute() on complete failure Leonid Vasiliev 2020-12-20 16:02 ` Vladislav Shpilevoy 2020-12-23 22:38 ` Leonid Vasiliev
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox