go-sqlcmd icon indicating copy to clipboard operation
go-sqlcmd copied to clipboard

sqlcmd does not handle/honor the command timeout (-t) flag properly on Linux

Open csommerolo opened this issue 3 months ago • 0 comments

sqlcmd does not properly handle/honor the SQL Command Timeout (-t) flag properly on Linux. It works fine on Windows but the command always "hangs" for ~10 minutes before finally exiting when run on a Linux system .

Testing Setup

Test Table

USE [dba]
GO

CREATE TABLE [dbo].[DBScriptTable](
	[id] [bigint] IDENTITY(1,1) NOT NULL,
	[placeName] [varchar](100) NULL,
    PRIMARY KEY CLUSTERED ([id] ASC) 
) ON [PRIMARY]
GO

Blocker DML

This script will create an open transaction against the above table with SERIALIZABLE transaction isolation level. Running it without completing the transaction will essentially block all operations on the table until the script is either rolled back or committed. That's why the ROLLBACK is commented out here.

-- This should be run from within SSMS so you can control the transaction
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;

BEGIN TRANSACTION

INSERT INTO DBscriptTable (placeName) VALUES ('Redmond, Washington') ;

--ROLLBACK TRANSACTION

Test DML

Simple select to use for our sqlcmd tests

-- Save as test.sql
SELECT * FROM DBScriptTable
GO

How to replicate this behavior

  1. Create the test table in a database named dba

  2. Run the Blocker DML with the ROLLBACK commented out from SSMS. This will block all operations on the table. Using something like sp_WhoIsActive you should be able to verify that we now have a sleeping session with an open transaction for this.

  3. Run sqlcmd script below in PowerShell on Windows 11. You will notice that this script will return immediately after the command timeout of 1 second

PS> get-date; sqlcmd -S "<redacted>" -U "<redacted>" -P "<redacted>" -i ./test.sql -d dba -t 1; get-date

Tuesday, August 12, 2025 10:20:26 AM
Timeout expired
Tuesday, August 12, 2025 10:20:27 AM

PS>
  1. Run the sqlcmd script below on a Linux system in bash. You will notice that the SQL "Timeout expired" message will appear after 1 second, but sqlcmd does not return us to a bash prompt for 10 minutes. I'm not exactly sure what it's waiting on here and this is the unexpected behavior.
$ date; sqlcmd -S "<redacted>" -U "<redacted>" -P "<redacted>" -i ./test.sql -d dba -t 1; date

Tue Aug 12 10:19:56 EDT 2025
Timeout expired
Tue Aug 12 10:29:57 EDT 2025

$
  1. Make sure you uncomment and execute the ROLLBACK in the SQL script to complete that transaction.

csommerolo avatar Aug 12 '25 15:08 csommerolo