-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
MDEV-36269: Improve error handling for source command
#4455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 10.11
Are you sure you want to change the base?
Conversation
|
The only unit test that fails here: buildbot/amd64-windows passes successfully locally. |
client/mysql.cc
Outdated
| char buff[FN_REFLEN+60]; | ||
| sprintf(buff, "'%s' is a directory, not a file", source_name); | ||
| return put_info(buff, INFO_ERROR, 0); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you look in client/readline.cc at the batch_readline_init its almost doing the same check.
If you look at the other call of batch_readline_init in this fine where stdin is passed, it just errors based on the return result of the batch_readline_init.
I recommend doing the same, just handle batch_readline_init the same way. Extend message to include potential memory allocation failure.
For tests - recommend adding someting in mysql-test/main/mysql_client_test.test. Something with -e "source $MASTER_MYSOCK" perhaps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes addressed here
For .test and .result files I tried to use the environment variable I found here:
Line 45 in 809e6f4
| ${CMAKE_SOURCE_DIR}/cmake ${CMAKE_SOURCE_DIR}/cmake/Internal/CPack) |
like this
$CMAKE_SOURCE_DIR, but the test handled /client directory as a file and threw this error: ERROR at line 1: Failed to open file '/server/client', error: 2. So I will use my local relative path just for now.
For the current implementation of .test and .result files I would be grateful if you take a look at them and help me figure out how to solve this error:
mohammad@mohammad:~/open-source/mariaDB/build-mariadb-server-debug$ mysql-test/mtr mysql-test/main/mysql_client_test-mysql-source-errors.test
Logging: /home/mohammad/open-source/mariaDB/server/mysql-test/mariadb-test-run.pl mysql-test/main/mysql_client_test-mysql-source-errors.test
VS config:
vardir: /home/mohammad/open-source/mariaDB/build-mariadb-server-debug/mysql-test/var
Checking leftover processes...
Removing old var directory...
Creating var directory '/home/mohammad/open-source/mariaDB/build-mariadb-server-debug/mysql-test/var'...
Checking supported features...
MariaDB Version 10.6.25-MariaDB-debug
- SSL connections supported
- binaries are debug compiled
- binaries built with wsrep patch
Collecting tests...
Installing system database...
==============================================================================
TEST RESULT TIME (ms) or COMMENT
--------------------------------------------------------------------------
worker[01] Using MTR_BUILD_THREAD 300, with reserved ports 19000..19029
main.mysql_client_test-mysql-source-errors [ fail ]
Test ended at 2025-11-24 13:56:06
CURRENT_TEST: main.mysql_client_test-mysql-source-errors
ERROR at line 1: Failed to read from '/home/mohammad/open-source/mariaDB/server/client': it is a directory, or memory allocation failed
--- /home/mohammad/open-source/mariaDB/server/mysql-test/main/mysql_client_test-mysql-source-errors.result 2025-11-24 13:55:59.185361398 +0200
+++ /home/mohammad/open-source/mariaDB/server/mysql-test/main/mysql_client_test-mysql-source-errors.reject 2025-11-24 13:56:06.678022007 +0200
@@ -5,4 +5,3 @@
#
# Try to SOURCE the /client directory (should fail)
#
-ERROR: Failed to read from '/home/mohammad/open-source/mariaDB/server/client': it is a directory, or memory allocation failed
Result length mismatch
- saving '/home/mohammad/open-source/mariaDB/build-mariadb-server-debug/mysql-test/var/log/main.mysql_client_test-mysql-source-errors/' to '/home/mohammad/open-source/mariaDB/build-mariadb-server-debug/mysql-test/var/log/main.mysql_client_test-mysql-source-errors/'
--------------------------------------------------------------------------
The servers were restarted 0 times
Spent 0.000 of 4 seconds executing testcases
Failure: Failed 1/1 tests, 0.00% were successful.
Failing test(s): main.mysql_client_test-mysql-source-errors
The log files in var/log may give you some hint of what went wrong.
If you want to report this error, MariaDB's bug tracker is found at
https://jira.mariadb.org
mysql-test-run: *** ERROR: there were failing test cases
mohammad@mohammad:~/open-source/mariaDB/build-mariadb-server-debug$
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
source . is probably going to be simplest solution. But your test won't work on Windows anyway, since the check for file type is under #ifndef _WIN32.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
source .is probably going to be simplest solution.
Should it look like this:
in .test
--exec $MYSQL -e "source ."
and in .result
ERROR: Failed to read from '.': it is a directory, or memory allocation failed
?
I tried that but it still fails although I have ubuntu installed on my machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. How it fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the issue is caused by the test framework expecting a strict match between the error message in the .result file and the actual error message produced during the test. You can see this in the following output:
worker[01] Using MTR_BUILD_THREAD 300, with reserved ports 19000..19029
main.mysql_client_test-mysql-source-errors [ fail ]
Test ended at 2025-11-24 17:30:54
CURRENT_TEST: main.mysql_client_test-mysql-source-errors
ERROR at line 1: Failed to read from '.': it is a directory, or memory allocation failed
--- /home/mohammad/open-source/mariaDB/server/mysql-test/main/mysql_client_test-mysql-source-errors.result 2025-11-24 15:25:50.676723768 +0200
+++ /home/mohammad/open-source/mariaDB/server/mysql-test/main/mysql_client_test-mysql-source-errors.reject 2025-11-24 17:30:54.452501704 +0200
@@ -5,4 +5,3 @@
#
# Try to SOURCE the current directory (should fail)
#
-ERROR: Failed to read from '.': it is a directory, or memory allocation failed
Result length mismatchHowever, when I run the server and test the changes, it displays the intended error message!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue is that when we use --exec $MYSQL -e "source .", the error message goes to stderr, but the mtr framework is only capturing stdout in the result comparison. So it should look like this: --exec $MYSQL -e "source ." 2>&1
new changes addressed here
svoj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check #3935, specifically #3935 (review). This code should be slightly refactored to look good.
1f1cba1 to
5b6b826
Compare
|
Thank you both for the feedback. @svoj, I appreciate the refactoring suggestion. @grooverdan, since you initially reviewed this, I'd value your input on which approach to take before proceeding. |
grooverdan
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you move the test to the end of mysql-test/main/mysql_client_test.test this will resolve the embedded test failure (there's no client/server in embedded mode).
Rebase all commits onto the 10.11 branch, and squash them, include a commit message saying why these changes occurred. When finished git push --force and edit the github PR title to have 10.11 as the target branch.
At the end of the tests in mysql-test/main/mysql_client_test.test, put a --echo End of 10.11 tests. This is a standard practice to make it easier to resolve merge conflicts where multiple branches added tests. mtr --record mysql_client_test will update the result file in case you haven't discovered this, it doesn't need to be a manual edit (though do verify the contents).
| --echo # Try to SOURCE the current directory (should fail) | ||
| --echo # | ||
|
|
||
| --error 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To resolve the difference in output on Windows:
| --error 1 | |
| --replace_regex /(ERROR at line 1: Failed to).*/\1 REPLACED/ | |
| --error 1 |
client/mysql.cc
Outdated
| my_fclose(sql_file,MYF(0)); | ||
| return put_info("Can't initialize batch_readline", INFO_ERROR, 0); | ||
| char buff[FN_REFLEN+200]; | ||
| sprintf(buff, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use a snprintf(sizeof(buff),...
client/mysql.cc
Outdated
| return put_info("Can't initialize batch_readline", INFO_ERROR, 0); | ||
| char buff[FN_REFLEN+200]; | ||
| sprintf(buff, | ||
| "Failed to read from '%s': it is a directory, or memory allocation failed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a modifier on %s to restrict the message to the right most portion of the source_name. Adjust buffer size accordingly.
Message should be ".. it is a directory, block device, or memory allocation failed". Adjust the other batch_readline_init error message to be consistent with this.
Works for me too. Duplicating error message isn't productive. |
source command with directoriessource command
7725fe4 to
7c64e5e
Compare
7c64e5e to
a0d870e
Compare
svoj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice. Some minor polishing left.
client/readline.cc
Outdated
|
|
||
| static bool init_line_buffer(LINE_BUFFER *buffer,File file,ulong size, | ||
| ulong max_size); | ||
| bool init_line_buffer(LINE_BUFFER *buffer, File file, ulong size, ulong max_size); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this line, it shouldn't be needed anymore.
|
|
||
| --echo # | ||
| --echo # Try to SOURCE the current directory (should fail) | ||
| --echo # |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant, you already say "Test that SOURCE on an existent directory returns a clear error" a few lines above.
|
|
||
| --replace_regex /(ERROR at line 1: Failed to).*/\1 REPLACED/ | ||
| --error 1 | ||
| --exec $MYSQL -e "source ." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot 2>&1? There's no error in the result file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I misunderstood @grooverdan 's review.
| --echo # Try to SOURCE the current directory (should fail) | ||
| --echo # | ||
|
|
||
| --replace_regex /(ERROR at line 1: Failed to).*/\1 REPLACED/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to think more about it. Ideally the same error should be returned on Windows. No action needed at the moment.
client/my_readline.h
Outdated
| } LINE_BUFFER; | ||
|
|
||
| extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file); | ||
| extern LINE_BUFFER *batch_readline_init(ulong max_size, const char *path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this line.
client/mysql.cc
Outdated
| return -1; | ||
| } | ||
|
|
||
| LINE_BUFFER *batch_readline_init(ulong max_size, const char *path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be static.
client/mysql.cc
Outdated
| if (path) | ||
| my_close(file, MYF(0)); | ||
| put_info(buff, INFO_ERROR, 0); | ||
| return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To avoid code duplication, MariaDB common practice would be to use something like this:
...
goto err;
err1:
put_info(buff, INFO_ERROR, 0);
err:
if (path)
my_close(file, MYF(0));
return 0;
These labels should be after return line_buff.
a0d870e to
62f4505
Compare
svoj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More issues outlined.
client/mysql.cc
Outdated
| { | ||
| my_snprintf(buff, sizeof(buff), "Failed to open file '%.*s', error: %d", | ||
| FN_REFLEN, path, my_errno); | ||
| goto err1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't goto err1 from this point, as it will have to issue close(-1). Just do put_info() here.
client/mysql.cc
Outdated
| my_snprintf(buff, sizeof(buff), "Failed to stat file '%.*s', error: %d", | ||
| FN_REFLEN, path ? path : "stdin", my_errno); | ||
| goto err1; | ||
| goto err; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here and everywhere else, remove second goto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean replace it with :
if (path)
my_close(file, MYF(0));
return 0;
or remove it totally?
EDIT: yeah I think I understand now. goto err1 will lead to run err:.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Second goto is never reachable anyway.
62f4505 to
7ff95d4
Compare
svoj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Few more issues. Please also fix commit message according to https://github.com/MariaDB/server/blob/main/CODING_STANDARDS.md.
Specifically lines must be under 72 characters.
| --echo # Test that SOURCE on an existent directory returns a clear error | ||
| --echo # | ||
|
|
||
| # --replace_regex /(ERROR at line 1: Failed to).*/\1 REPLACED/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this line.
client/mysql.cc
Outdated
| { | ||
| my_fclose(sql_file,MYF(0)); | ||
| return put_info("Can't initialize batch_readline", INFO_ERROR, 0); | ||
| return 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has to be return ignore_errors ? -1 : 1;
client/mysql.cc
Outdated
| } | ||
|
|
||
| #ifdef _WIN32 | ||
| #else |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, please do #ifndef _WIN32.
7ff95d4 to
43af148
Compare
dfb9afe to
82ed328
Compare
|
@MohamedM216 I pushed 056e85f with coding style fixes to your branch. Please get it "fixup"-ed if you agree. Or I can do that myself. Also we need to sort out failure on Windows. It looks like some sort of segmentation fault or stack overflow due to our Windows specific code. I have no idea how to debug it effectively at the moment. So I slightly modified the code, let's see how it works. With these things completed, I think I can approve this pr. |
056e85f to
d02e3bc
Compare
d02e3bc to
b91b86c
Compare
b91b86c to
6ebd647
Compare
|
@MohamedM216 it appears I broke your last force push with my force push. Sorry for the mess. Feel free to update it now. |
|
I think I found a bug: it calls |
528a18e to
84e21da
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
client/mysql.cc
Outdated
| if (my_errno == EACCES && my_stat(path, &input_file_stat, MYF(0)) && | ||
| MY_S_ISDIR(input_file_stat.st_mode)) | ||
| my_snprintf(buff, sizeof(buff), "Can't read from a directory '%.*s'", | ||
| FN_REFLEN, path ? path : "stdin"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here path is always set, no need to path ? path : "stdin", missed this when copy-pasting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
@grooverdan will you want to have another look? |
589115b to
7cd2cea
Compare
- refactor batch_readline_init to mysql.cc for proper error handling - add unit test and move it to the end of main/mysql_client_test.test to resolve embedded test failures - remove unnecessary code and duplicates to clean up implementation - redirect error message from stderr to stdout in .test file - use labels to avoid code duplication - handle windows check for block device - ensure file failing to open in windows because being a directory is different from any other reason for clear error message
7cd2cea to
553bd3e
Compare
@grooverdan just a gentle ping on this when you have a moment. Thanks! |
Description
This PR provides a descriptive error message when users accidentally use a directory with the
sourcecommand instead of getting an ambiguous error message:Can't initialize batch_readline.Release Notes
How can this PR be tested?
Create a local branch tracking the upstream branch
10.6.Then build and start the server as mentioned here
And after running these commands you will get the desired output (descriptive error message):
Basing the PR against the correct MariaDB version
mainbranch.PR quality check