The latest sqsh for FreeTDS (loaded as sqsh-2.5-1.el6.x86_64.x86_64.rpm) consistently generates "Segmentation fault" error every time sqsh fails on connection to MS SQL server. For instance:
iebdev21 [05:19 PM] ~> ~/sa/MSSQL/sqsh-ms/sqsh-2.5/RPM/usr/bin/sqsh -v
sqsh-2.5
iebdev21 [05:20 PM] ~> ~/sa/MSSQL/sqsh-ms/sqsh-2.5/RPM/usr/bin/sqsh -C "set nocount on" -S MSSQL777 -U xxx -P yyy
Open Client Message
Layer 0, Origin 0, Severity 78, Number 44
Server name not found in configuration files.
Open Client Message
Layer 0, Origin 0, Severity 78, Number 45
Unknown host machine name.
Segmentation fault
iebdev21 [05:20 PM] ~> echo $?
139
Since this is the binary from prebuild package (downloaded from sourceforge), it hopefully would not be a problem to reproduce the reported behavior. Please note: it doesn't matter what was the cause of connection failure - wrong login name, password or server was down. In any case sqsh segfaults.
Actually same happens with every sqsh version (for freetds) I tested: 2.1.4, 2.1.7, 2.1.8 and 2.4.
Unfortunately I am not able to reproduce this behaviour. I have a strong feeling this segmentation fault comes from your freetds implementation. Which version of FreeTDS have you installed? Is it installed as a pre-built package or did you built it yourself? The sqsh package is built against freetds-0.91-2.el6.x86_64.
I will explain a little bit further how sqsh interacts with the FreeTDS libct library. When you start sqsh with a couple of connection specific parameters like -S, -U, -P (but also parameter settings regarding language, TDS package size, character set, etc.), these are being handled by the cmd_connect() function of sqsh and that will make subsequent function calls to CT-library (FreeTDS) to set/activate these provided parameters and finally a call will be made to ct_connect() that will actually perform the connection setup to the database server. If something with ct_connect() fails, it will be reported by the callback message handlers coded in sqsh and control is then returned back to the CT-library again. Normally speaking, when all messages/errors are processed by the callback handlers, the ct_connect() call should return back to sqsh with a return code not equal to CS_SUCCEED and sqsh would then cleanup and exit with returncode 255. In your case a segmentation fault occurs after the error messages are displayed. So the fault could still be in ct_connect() or cleanup processing of sqsh, which also makes some CT-library calls.
If you have gdb installed you could try to analyze the core file or run sqsh through gdb to find the failing function. To inspect a core file you could do:
or
to find out which libraries are loaded by sqsh you could run
The libct.so.4 specifies the related shared object file of FreeTDS. Please let me know your results.
PS, I note you have installed sqsh in another location so you have to provide your own path to sqsh of course in the above examples
Hi Martin!
Thanks a lot for detail instructions. I will follow them all, but first I'd like to make sure we're on the same page. I wonder if you can try to run sqsh command with "-C" option, like the one I showed in initial post. Something like
sqsh -S xxx -U yyy -P zzz -C "any command or anything"
Now about software I used. Previously I ran the test against freetds loaded from www.freetds.org (freetds-stable.tgz), which then I built myself. I couldn't find there freetds version you mentioned in your post, but then got freetds-0.91-2.el6.x86_64.rpm from http://ftp.linux.ncsu.edu/mirror/ftp.redhat.com/pub/epel/6/x86_64. This is pre-built package, so I didn't need to build it myself. sqsh itself is also loaded as RPM package sqsh-2.5-1.el6.x86_64.x86_64.rpm from https://sourceforge.net/projects/sqsh/files/sqsh/sqsh-2.5 - i.e. it's your build.
In gdb we are not getting all details:
Running sqsh under gdb basically gives the same output.
But previously I had this test run with sqsh and freetds I build myself with debug options.
And then I've got a bit more info:
Please let me know if you need more data.
Hi Slava,
You are absolutely right. When using the -C option I can reproduce the segmentation fault indeed. What happens when you add the -C option to the commandline is that another codepath is executed and cmd_go is called first. This functions checks if a connection is already established and if not, calls cmd_connect to setup a server connection (via a call to jobset_run(..,"\connect",..)). However, the return status of cmd_connect is not checked correctly and code processing in cmd_go() continues and finally fails if a ct_cmd_alloc() is called with a NULL connection pointer. The difference here with Sybase CT-Library is that the Sybase functions do some sanity checks and just return CS_FAIL when called with a NULL connection pointer, where FreeTDS does not check on this and runs into the segmentation fault.
The solution is to add an additional check on the return status of cmd_connect (via jobset_run(g_jobset,"\connect",&exit_status)). Not only the return value of jobset_run itself needs to be checked, but also the value of exit_status. There are a couple of other flaws in the code with the same error.
I will provide a fix in the next release.
Thanks for your report and your help with this.
Best Regards,
Martin.
Thanks for prompt feedback and cooperation, Martin! Hope this fix will be out soon. Now it's up to you to close this ticket or leave open. I have one more note about option "-I" not working with sqsh/freetds, but probably it should go to a separate ticket. Please advise.
Hi Slava,
Ik will close the ticket when the bug is fixed in the next release.
Regarding the -I option with sqsh on FreeTDS, that is a known issue. FreeTDS currently does not support this and silently ignores interfaces or freetds.conf files provided with the -I parameter. Please have a look at thread
So what happens if you provide the -I parameter is that sqsh makes a call to ct_config() with the CS_IFILE property and a pointer to the expanded parameter string. However, the ct_config function in freetds-dev.0.92.377/src/ctlib/ct.c does not check for the CS_IFILE property in the switch statement and returns CS_SUCCEED by default. To solve this the FreeTDS project should add something minimalistic like this on line 2456 for example of the named source file:
This works for me.
Cheers,
Martin.
Sounds good on all counts, Martin. I think it might be useful to report "-I" issue to freetds, maybe we'll get to that later. Thanks for your help!
Hi Martin,
While I was looking for the ways sqsh and freetds handle interfaces file, I spotted that in line 1283 of cmd_connect.c the code looks a little unusual (to my ignorant opinion):
In other modules like cmd_go.c, cmd_do.c or freetds unit tests the similar condition is treated as a failure. I'm totally unfamiliar with this code, so it maybe all right. Just wanted to check with you whether it's what was supposed to be there.
Thanks for looking,
Slava.
Hi Slava,
Sorry for a late response but I was on holiday and not able to reply any sooner.
Yes, you are right that this code looks a bit strange. This part of the code will arrange for a "use <dbname>" command, (if required because of a -D parameter for example), after a connection is successfully setup. So basically the connection succeeded but if ct_cmd_alloc fails here, it will not issue the "use" command but go to connect_succeed anyway. I assume the author of this piece of code decided to go for a connect_succeed as the connection was still successful and handle CT problems later on. But this might still lead to undesired side-effects. So I think it is better to goto connect_fail here. I will fix it in the next release.
Thanks for pointing this out.
Best regards,
Martin.
Hope you had good holidays, Martin. And now I'm also back from vacation. :)
Thanks for looking into issue I reported in the last post. Seems like it should not be hard to fix.
All the best,
Slava.