How can I fix 22 invalid argument error(22)? - c++

I don't know why keep occurring [22] invalid argument in the process.
the source code like this
int MainLoop()
{
struct timeval timeout;
fd_set event;
int n, maxfd, newfd, rc, err_cnt = 0;
CSocket* pSocket;
int chktime, currtime;
char buff[MAX_PACKET_SIZE];
int MaxPosition, CurrPosition = 0;
WmBoard *pWmBoard;
MaxPosition = pCWmBoard->GetMaxPosition();
g_CAgent.Create(g_CsPort, g_CsAddr);
chktime = GetTime();
while(g_Running) {
timeout.tv_sec = 1; /* Second */
timeout.tv_usec = 0; /* micro Second */
pSocket = NULL;
maxfd = g_SockList.GetEventMask(&event);
n = select(maxfd, &event, (fd_set *)0,(fd_set *)0,
(struct timeval *) &timeout);
if(n > 0) {
pSocket = g_SockList.GetEventSock(&event);
if(pSocket != NULL)
{
newfd = pSocket->Accept();
if(newfd > 0)
{
err_cnt = 0;
pWmBoard = GetMinClientCH(MaxPosition);
if (pWmBoard != NULL)
{
rc = SendFD(pWmBoard->PipeFd, (void *)" ", 1, newfd);
if (rc <= 0)
{
char szTmp[128];
sprintf(szTmp,"FDSend Error=[%d]errno=[%d]",
newfd,errno);
g_CAgent.SendMessage("!S001", g_PgmName, szTmp);
g_Log.Write("[%s:%d][E] %s",
g_PgmName, g_Pid, szTmp);
/*
if(errno == EBADF) g_Running = FALSE;
*/
#if 0
if(pWmBoard -> ProcessID > 1)
kill(pWmBoard->ProcessID, SIGTERM);
#endif
pWmBoard->PipeFd = -1;
}
}
else
{
g_Log.Write("[%s:%d][E] client is full. value=%d",
g_PgmName, g_Pid, g_CurrCHPos);
g_Running = FALSE;
}
close(newfd);
}
else
{
g_Log.Write("[%s:%d][E] accept error. errno = [%d]",
g_PgmName, g_Pid, errno);
switch(errno)
{
case EMFILE : break; /* Too many open files */
case ENOENT : /* No such file or directory */
case EAGAIN : /* Try again */
case EINVAL : /* Invalid argument */
case ENOMSG : ; /* No message of desired type */
default :
ResetSocket();
}
}
}
else
g_Log.Write("[%s:%d] GetEventSock is NULL", g_PgmName, g_Pid);
}
else if (n == 0) {
currtime = GetTime();
if( currtime == 0 && chktime != currtime)
{ // ¸ÅÀÏ ÁöÁ¤ÇÑ ½Ã°£ (24½Ã)
g_Log.ReOpen();
g_MaxUser = 0;
ClearTotalTR();
}
chktime = currtime;
}
if (getppid() <= 1){
g_Running = FALSE;
}
if(WhatTime()) SendWmBoardInfo();
}
g_CAgent.Close();
return FALSE;
}
We call the process as WmCL and the WmCL send data to WmCH for connection.
and I got log using strace command the result same as below.
select(19, [16 17 18], NULL, NULL, {1, 0}) = 1 (in [17], left {0, 914250})
accept(17, {sa_family=AF_INET, sin_port=htons(38610), sin_addr=inet_addr("114.122.207.70")}, [16]) = 20
sendmsg(9, {msg_name(0)=NULL, msg_iov(1)=[{" ", 1}], msg_controllen=24, {cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, {20}}, msg_flags=MSG_OOB|MSG_DONTROUTE|MSG_CTRUNC|0x10}, 0) = 1
close(20) = 0
getppid() = 17099
select(19, [16 17 18], NULL, NULL, {1, 0}) = 0 (Timeout)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=344, ...}) = 0
getppid() = 17099
select(19, [16 17 18], NULL, NULL, {1, 0}) = 0 (Timeout)
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=344, ...}) = 0
getppid() = 17099
select(19, [16 17 18], NULL, NULL, {1, 0}) = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=18976, si_status=0, si_utime=1173, si_stime=797} ---
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG, NULL) = 18976
close(7) = 0
stat("/etc/localtime", {st_mode=S_IFREG|0644, st_size=344, ...}) = 0
sendto(19, "m20192.168.103.22 1028360WmCL "..., 161, 0, {sa_family=AF_INET, sin_port=htons(8499), sin_addr=inet_addr("192.168.201.17")}, 16) = 161
write(5, "[10:28:36-000002][WmCL:17236][E]"..., 63) = 63
socketpair(PF_LOCAL, SOCK_STREAM, 0, [7, 20]) = 0
clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f287d4219f0) = 23210
close(20) = 0
as following the log, 'select' result is '?' but I don't know why the result is '?'....
Can you advise to me to fix this problem?

Related

0xC0000005: Access violation reading location 0x005EF9E4

I am having issues with Handles. I have Bytebeat (music in bytes) playing inside of a DWORD WINAPI function. When I try to terminate and close the thread, it straight up gives me the error in the title. This is my code:
#include <windows.h>
#pragma comment(lib, "Winmm.lib")
DWORD WINAPI bytebeat1(LPVOID) {
while (1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 11000, 11000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[11000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t & t + t / 256) - t * (t >> 15) & 64;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
}
DWORD WINAPI bytebeat2(LPVOID) {
while (1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[8000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t, t / 5) >> t / 25 & t / 55 ^ t & 255 ^ (t / 150) ^ 2508025 * 24240835810 & (t / 100) * t / 6000 ^ 5000 * t / 2500 ^ 25 * t / 24;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
}
int main() {
HANDLE beat1 = CreateThread(0, 0, bytebeat1, 0, 0, 0);
Sleep(6000);
TerminateThread(beat1, 0); CloseHandle(beat1);
Sleep(1000);
HANDLE beat2 = CreateThread(0, 0, bytebeat2, 0, 0, 0);
Sleep(6000);
TerminateThread(beat2, 0); CloseHandle(beat2);
}
I do not know why this is happening. The only fix is compiling it with G++ but I want it so I could just build it. Any help is appreciated. Thanks!
As the documentation makes clear, you can't use TerminateThread this way. Instead, replace the calls to Sleep with an interruptible sleep function that will terminate the thread cleanly and safely if requested to do so.
When you call TerminateThread, you are basically force-crashing your threads. They still have their own stack allocated and handles to Windows resources. They aren't cleaned up properly, causing your crash.
Here's a simple example of how to close your threads without any error. In a real-world scenario this is an unprofessional solution, but it shows the bare minimum that you need to do.
#include <windows.h>
#pragma comment(lib, "Winmm.lib")
volatile bool quit1 = false;
volatile bool quit2 = false;
DWORD WINAPI bytebeat1(LPVOID) {
while (!quit1) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 11000, 11000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[11000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t & t + t / 256) - t * (t >> 15) & 64;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
return 0;
}
DWORD WINAPI bytebeat2(LPVOID) {
while (!quit2) {
HWAVEOUT hwo = 0;
WAVEFORMATEX wfx = { WAVE_FORMAT_PCM, 1, 8000, 8000, 1, 8, 0 };
waveOutOpen(&hwo, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL);
char buffer[8000 * 6];
for (DWORD t = 0; t < sizeof(buffer); t++)
buffer[t] = static_cast<char>(t, t / 5) >> t / 25 & t / 55 ^ t & 255 ^ (t / 150) ^ 2508025 * 24240835810 & (t / 100) * t / 6000 ^ 5000 * t / 2500 ^ 25 * t / 24;
WAVEHDR hdr = { buffer, sizeof(buffer), 0, 0, 0, 0, 0, 0 };
waveOutPrepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutWrite(hwo, &hdr, sizeof(WAVEHDR));
waveOutUnprepareHeader(hwo, &hdr, sizeof(WAVEHDR));
waveOutClose(hwo);
Sleep(6000);
}
return 0;
}
int main() {
HANDLE beat1 = CreateThread(0, 0, bytebeat1, 0, 0, 0);
Sleep(6000);
quit1 = true;
WaitForSingleObject(beat1, INFINITE);
CloseHandle(beat1);
Sleep(1000);
HANDLE beat2 = CreateThread(0, 0, bytebeat2, 0, 0, 0);
Sleep(6000);
quit2 = true;
WaitForSingleObject(beat2, INFINITE);
CloseHandle(beat2);
}

odbc binding to datetime column fails on Linux but works on Windows

Our C++ code on Windows uses ODBC to talk to SQL Server.
We are in the process of porting to Linux and
getting this ODBC error for a datetime Stored Procedure argument.
Datetime field overflow. Fractional second precision exceeds the scale specified in the parameter binding.
Googling that error says to set scale to 3 on the ODBC bind.
We do that and it works on Windows but not Linux.
Here is a semi small code sample that reproduces the problem.
The sample is 330 lines of C++ and 100 lines of SQL.
(The original is 1000 times bigger.)
It seems to be related to a blob SP argument.
datetime before the blob work, and those after the blob fail.
I tried making a 3 column test table with (datetime, blob, datetime)
but the problem did not happen.
On Windows this test inserts 820 rows while
on Linux it inserts 700 because 120 fail.
Windows has "ODBC Driver 17 for SQL Server".
Linux is Ubuntu 20.04, unixODBC 2.3.7, ODBC 17.7
Create a database name bgb_test2.
Create a DSN named bgb8_sql2016 pointing to DB server.
Add SQL user 'bgb' with password 'Abc-123'.
Or change the code as you like.
SQL code
USE [bgb_test2]
GO
/****** Object: StoredProcedure [dbo].[sp_TTemporalAccounts_ins] Script Date: 5/28/2021 11:46:19 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[TTemporalAccounts](
[acctId] [int] NOT NULL,
[rowClassifier] [char](16) NULL,
[grpClassifier] [char](16) NULL,
[LAD] [datetime] NULL,
[LAPD] [datetime] NULL,
[NAD] [datetime] NULL,
[AccountBlob] [text] NULL,
[StatementDate] [datetime] NULL,
[postBalance] [money] NULL,
[Balance] [money] NULL,
[CountDe] [int] NULL,
[bucketMTD1] [money] NULL,
[bucketMTD2] [money] NULL,
[bucketMTD3] [money] NULL,
[bucketCTD1] [money] NULL,
[bucketCTD2] [money] NULL,
[bucketCTD3] [money] NULL,
[parent01ATID] [int] NULL,
[parent01AID] [int] NULL,
[parent02ATID] [int] NULL,
[parent02AID] [int] NULL,
[parent03ATID] [int] NULL,
[parent03AID] [int] NULL,
[VisaInterestRate] [money] NULL,
[VisaLateCharge] [money] NULL,
[VisaParam1] [money] NULL,
[VisaParam2] [money] NULL,
[VisaParam3] [money] NULL,
[VisaParam4] [money] NULL,
[VisaParam5] [money] NULL,
[VisaParam6] [money] NULL,
[VisaParam7] [money] NULL,
[VisaParam8] [money] NULL,
[tpyNAD] [datetime] NULL,
[tpyLAD] [datetime] NULL,
[tpyBlob] [text] NULL,
[param_sig] [int] NULL,
[param_state] [varchar](171) NULL,
[param_lcd] [datetime] NULL,
[param_fvt] [datetime] NULL,
[_paramlvt] [datetime] NULL,
CONSTRAINT [csPk_TTemporalAccounts] PRIMARY KEY CLUSTERED
(
[acctId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
CREATE PROCEDURE [dbo].[sp_TTemporalAccounts_ins] (
#acctId int, #rowClassifier char (16), #grpClassifier char (16),
#LAD datetime, #LAPD datetime, #NAD datetime,
#AccountBlob text, #StatementDate datetime, #postBalance money,
#Balance money, #CountDe int,
#bucketMTD1 money, #bucketMTD2 money, #bucketMTD3 money,
#bucketCTD1 money, #bucketCTD2 money, #bucketCTD3 money,
#parent01ATID int, #parent01AID int,
#parent02ATID int, #parent02AID int,
#parent03ATID int, #parent03AID int,
#VisaInterestRate money, #VisaLateCharge money,
#VisaParam1 money, #VisaParam2 money, #VisaParam3 money,
#VisaParam4 money, #VisaParam5 money, #VisaParam6 money,
#VisaParam7 money, #VisaParam8 money,
#tpyNAD datetime, #tpyLAD datetime, #tpyBlob text,
#param_sig int, #param_state varchar (171),
#param_lcd datetime, #param_fvt datetime, #_paramlvt datetime
) AS SET NOCOUNT ON; SET ANSI_NULLS ON; SET ANSI_PADDING ON; SET ANSI_WARNINGS ON; SET ARITHABORT ON; SET QUOTED_IDENTIFIER ON; SET CONCAT_NULL_YIELDS_NULL ON; SET NUMERIC_ROUNDABORT OFF;
INSERT INTO TTemporalAccounts ( [acctId], [rowClassifier], [grpClassifier], [LAD], [LAPD], [NAD],
[AccountBlob], [StatementDate], [postBalance], [Balance], [CountDe], [bucketMTD1], [bucketMTD2], [bucketMTD3],
[bucketCTD1], [bucketCTD2], [bucketCTD3], [parent01ATID], [parent01AID], [parent02ATID], [parent02AID],
[parent03ATID], [parent03AID], [VisaInterestRate], [VisaLateCharge],
[VisaParam1], [VisaParam2], [VisaParam3], [VisaParam4], [VisaParam5], [VisaParam6], [VisaParam7], [VisaParam8],
[tpyNAD], [tpyLAD], [tpyBlob],
[param_sig], [param_state], [param_lcd], [param_fvt], [_paramlvt])
VALUES ( #acctId, #rowClassifier, #grpClassifier, #LAD, #LAPD, #NAD, #AccountBlob, #StatementDate,
#postBalance, #Balance, #CountDe, #bucketMTD1, #bucketMTD2, #bucketMTD3, #bucketCTD1, #bucketCTD2, #bucketCTD3,
#parent01ATID, #parent01AID, #parent02ATID, #parent02AID, #parent03ATID, #parent03AID,
#VisaInterestRate, #VisaLateCharge,
#VisaParam1, #VisaParam2, #VisaParam3, #VisaParam4, #VisaParam5, #VisaParam6, #VisaParam7, #VisaParam8,
#tpyNAD, #tpyLAD, #tpyBlob,
#param_sig, #param_state, #param_lcd, #param_fvt, #_paramlvt)
GO
C++ code
#ifdef WIN32
#ifdef _DEBUG
#define _ITERATOR_DEBUG_LEVEL 1
#endif
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <sal.h>
#endif
#include <string.h>
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <string>
// Binding to datetime column is failing on Linux
RETCODE
BBCheckForInfo(SQLSMALLINT HandleType, SQLHANDLE h, RETCODE rc, const char* api, const char* name = 0)
{
SQLCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN rc2;
long cpu_time = 0;
long elapsed_time = 0;
// Support growing these if needed
SQLCHAR* pMsg = Msg;
size_t MsgAlloc = sizeof(Msg);
if (name == 0) name = "";
// Print any errors or warnings.
if (rc != SQL_SUCCESS) {
// Get the status records.
i = 1;
while ((rc2 = SQLGetDiagRec(HandleType, h, i, SqlState, &NativeError, pMsg, MsgAlloc, &MsgLen)) == SQL_SUCCESS || rc2 == SQL_SUCCESS_WITH_INFO) {
if (rc2 == SQL_SUCCESS_WITH_INFO) {
printf("Msg[] too small, need %d bytes (have %d)\n", MsgLen, MsgAlloc);
if (pMsg != Msg) delete[] pMsg;
MsgAlloc = MsgLen + 100;
pMsg = new SQLCHAR[MsgAlloc + 10];
// Do not increment i so we retry getting the last error message
continue;
}
i++;
printf("Query %s API %s() Name %s State %s Native %d Msg %s\n",
name,
api,
name,
SqlState, NativeError, Msg);
} // while
if (rc2 != SQL_NO_DATA) {
printf("SQLGetDiagRec(%s) name %s returned %d\n", api, name, rc2);
}
} // if
if (pMsg != Msg) delete[] pMsg;
pMsg = 0;
if (rc == SQL_SUCCESS_WITH_INFO) rc = SQL_SUCCESS;
return rc;
}
enum class CI_type {
CI_int,
CI_char16,
CI_datetime,
CI_text,
CI_money,
CI_varchar171,
// CI_end
};
#define N_COL 41
struct ColInfo {
const char* name;
enum CI_type type;
} g_ColInfoArray[N_COL] = {
"acctId", CI_type::CI_int,
"rowClassifier", CI_type::CI_char16,
"grpClassifier", CI_type::CI_char16,
"LAD", CI_type::CI_datetime,
"LAPD", CI_type::CI_datetime,
"NAD", CI_type::CI_datetime,
"AccountBlob", CI_type::CI_text,
"StatementDate", CI_type::CI_datetime,
"postBalance", CI_type::CI_money,
"Balance", CI_type::CI_money,
"CountDe", CI_type::CI_int,
"bucketMTD1", CI_type::CI_money,
"bucketMTD2", CI_type::CI_money,
"bucketMTD3", CI_type::CI_money,
"bucketCTD1", CI_type::CI_money,
"bucketCTD2", CI_type::CI_money,
"bucketCTD3", CI_type::CI_money,
"parent01ATID", CI_type::CI_int,
"parent01AID", CI_type::CI_int,
"parent02ATID", CI_type::CI_int,
"parent02AID", CI_type::CI_int,
"parent03ATID", CI_type::CI_int,
"parent03AID", CI_type::CI_int,
"VisaInterestRate", CI_type::CI_money,
"VisaLateCharge", CI_type::CI_money,
"VisaParam1", CI_type::CI_money,
"VisaParam2", CI_type::CI_money,
"VisaParam3", CI_type::CI_money,
"VisaParam4", CI_type::CI_money,
"VisaParam5", CI_type::CI_money,
"VisaParam6", CI_type::CI_money,
"VisaParam7", CI_type::CI_money,
"VisaParam8", CI_type::CI_money,
"tpyNAD", CI_type::CI_datetime,
"tpyLAD", CI_type::CI_datetime,
"tpyBlob", CI_type::CI_text,
"param_sig", CI_type::CI_int,
"param_state", CI_type::CI_varchar171,
"param_lcd", CI_type::CI_datetime,
"param_fvt", CI_type::CI_datetime,
"_paramlvt", CI_type::CI_datetime,
// { 0, CI_type::CI_end }
};
void
main()
{
std::string ConStr;
ConStr += ";DSN=bgb8_sql2016"; // change
ConStr += ";DATABASE=bgb_test2";
ConStr += ";UID=bgb;PWD=Abc-123"; // change
ConStr += ";APP=DBB";
// const char* computername = dbbGetenv("COMPUTERNAME");
ConStr += ";WSID=host";
// ConStr += computername;
ConStr += ";AutoTranslate=no";
SQLHENV hEnv;
int rc;
rc = SQLAllocEnv(&hEnv);
rc = SQLSetEnvAttr(hEnv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
rc = BBCheckForInfo(SQL_HANDLE_ENV, hEnv, rc, "SQLSetEnvAttr", "SQL_ATTR_ODBC_VERSION");
SQLHDBC hDbc;
rc = SQLAllocConnect(hEnv, &hDbc);
rc = BBCheckForInfo(SQL_HANDLE_ENV, hEnv, rc, "SQLAllocConnect()");
// rc = SQLSetConnectAttr(hDbc, SQL_COPT_SS_BCP, (void*)SQL_BCP_ON, SQL_IS_INTEGER);
// BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLSetConnectAttr", "SQL_COPT_SS_BCP");
short outlen = 0;
UCHAR outbuf[2048];
rc = SQLDriverConnect(hDbc, NULL, (UCHAR*)ConStr.c_str(), ConStr.length(), outbuf, sizeof(outbuf), &outlen, SQL_DRIVER_NOPROMPT);
rc = BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLDriverConnect()");
SQLHSTMT hstmt;
SQLAllocStmt(hDbc, &hstmt);
rc = BBCheckForInfo(SQL_HANDLE_DBC, hDbc, rc, "SQLAllocStmt()");
int skey = 0;
for (int rows = 0; rows < 20; rows++) {
// for x in 0 .. 2^N_COL-1
// (c in x) means set col, else NULL
// Inserting 2^41 rows may hit practical limitations (BOOM)
for (int nn = 0; nn < N_COL; nn++) {
void* mem[N_COL];
for (int c = 0; c < N_COL; c++) {
// Set PK and column nn to values, rest are NULL
SQLHSTMT StatementHandle = hstmt;
SQLUSMALLINT ParameterNumber = c + 1;
SQLSMALLINT InputOutputType = SQL_PARAM_INPUT;
SQLSMALLINT ValueType = -1;
SQLSMALLINT ParameterType = -1;
SQLULEN ColumnSize = 0;
SQLSMALLINT DecimalDigits = 0;
SQLPOINTER ParameterValuePtr = 0;
SQLLEN BufferLength = 0;
SQLLEN* StrLen_or_IndPtr = 0;
switch (g_ColInfoArray[c].type) {
case CI_type::CI_int:
ValueType = SQL_C_DEFAULT;
ParameterType = SQL_INTEGER;
break;
case CI_type::CI_char16:
ValueType = SQL_C_CHAR;
ParameterType = SQL_CHAR;
ColumnSize = 16;
break;
case CI_type::CI_datetime:
ValueType = SQL_C_TYPE_TIMESTAMP;
ParameterType = SQL_TYPE_TIMESTAMP;
ColumnSize = 23;
DecimalDigits = 3;
break;
case CI_type::CI_text:
ValueType = SQL_C_CHAR;
ParameterType = SQL_LONGVARCHAR;
ColumnSize = 100;
break;
case CI_type::CI_money:
ValueType = SQL_C_CHAR;
ParameterType = SQL_VARCHAR;
break;
case CI_type::CI_varchar171:
ValueType = SQL_C_CHAR;
ParameterType = SQL_CHAR;
ColumnSize = 171;
break;
}
// (c == 0) is Primary Key
int value = 5;
if (c == 0) value = skey++;
if (c == 0 || c == nn) {
switch (g_ColInfoArray[c].type) {
case CI_type::CI_int:
{
SQLINTEGER* p = new SQLINTEGER;
mem[c] = p;
*p = value;
}
break;
case CI_type::CI_char16:
{
BufferLength = 16;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
case CI_type::CI_datetime:
{
SQL_TIMESTAMP_STRUCT* p = new SQL_TIMESTAMP_STRUCT;
mem[c] = p;
p->year = 2021;
p->month = 5;
p->day = 27;
p->hour = 20;
p->minute = 21;
p->second = 0;
p->fraction = 0;
}
break;
case CI_type::CI_text:
{
BufferLength = 100;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
case CI_type::CI_money:
{
BufferLength = 10;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "555.55");
}
break;
case CI_type::CI_varchar171:
{
BufferLength = 171;
char* p = new char[BufferLength + 1];
mem[c] = p;
strcpy(p, "five");
}
break;
}
ParameterValuePtr = mem[c];
}
else {
SQLLEN* p = new SQLLEN;
mem[c] = p;
*p = SQL_NULL_DATA;
StrLen_or_IndPtr = p;
}
rc = SQLBindParameter(StatementHandle, ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize, DecimalDigits, ParameterValuePtr, BufferLength, StrLen_or_IndPtr);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter");
} // for
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
for (int c = 0; c < N_COL; c++) {
delete mem[c];
}
} // for
} // for
#if 0
// Table has (int, datetime, text, datetime)
// Did not fail like expected
SQLINTEGER null = SQL_NULL_DATA;
// rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
// rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
// rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?)}", SQL_NTS);
// rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
// SQLcancel
SQL_TIMESTAMP_STRUCT ts;
ts.year = 2021;
ts.month = 5;
ts.day = 27;
ts.hour = 20;
ts.minute = 21;
ts.second = 0;
ts.fraction = 0;
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, &ts, 0, 0);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_LONGVARCHAR, 23, 3, 0, 0, &null);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLBindParameter(hstmt, 3, SQL_PARAM_INPUT, SQL_C_TYPE_TIMESTAMP, SQL_TYPE_TIMESTAMP, 23, 3, &ts, 0, 0);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLBindParameter()");
rc = SQLExecDirect(hstmt, (SQLCHAR*)"{call [sp_TTemporalAccounts_ins](?,?,?)}", SQL_NTS);
rc = BBCheckForInfo(SQL_HANDLE_STMT, hstmt, rc, "SQLExecDirect()");
// Bindings remain in effect until the application calls SQLBindParameter again,
// calls SQLFreeStmt with the SQL_RESET_PARAMS option,
// or calls SQLSetDescField to set the SQL_DESC_COUNT header field of the APD to 0
#endif
}

Zeroes after each value that has been sent over serial communication

I try to learn C++ by doing everything on it. However, I stuck while establishing serial communication over C++. I send an integer array over MCU(microcontroller) to the VS C++. I have no any software problem on the MCU side(I have tested). Additionally I can read char values correctly. However, when I read values by C++ I get 0 after each integer I read. I couldn't solve the problem, while I think that 0 corresponds to the newline.
For example if I send (5, 10, 15), I read (5, 0, 10, 0, 15, 0).
Can you help me in order to solve the problem? I am using Windows Api for serial communication.
The relevant code:
char ReadData; //temperory Character
int SerialBuffer[64] = { 0 }; //Buffer to send and receive data
.
.
.
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
SerialBuffer[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
The whole code:
int main(void)
{
HANDLE hComm; // Handle to the Serial port
BOOL Status; // Status
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
COMMTIMEOUTS timeouts = { 0 }; //Initializing timeouts structure
int SerialBuffer[64] = { 0 }; //Buffer to send and receive data
DWORD BytesWritten = 0; // No of bytes written to the port
DWORD dwEventMask; // Event mask to trigger
char ReadData; //temperory Character
DWORD NoBytesRead; // Bytes read by ReadFile()
unsigned char loop = 0;
wchar_t pszPortName[10] = { 0 }; //com port id
wchar_t PortNo[20] = { 0 }; //contain friendly name
hComm = CreateFile("\\\\.\\COM6", //friendly name
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
{
printf_s("\n Port can't be opened\n\n");
}
//Setting the Parameters for the SerialPort
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE)
{
printf_s("\nError to Get the Com state\n\n");
}
dcbSerialParams.BaudRate = CBR_115200; //BaudRate = 9600
dcbSerialParams.ByteSize = 8; //ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; //StopBits = 1
dcbSerialParams.Parity = NOPARITY; //Parity = None
Status = SetCommState(hComm, &dcbSerialParams);
if (Status == FALSE)
{
printf_s("\nError to Setting DCB Structure\n\n");
}
//Setting Timeouts
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE)
{
printf_s("\nError to Setting Time outs");
}
Status = SetCommMask(hComm, EV_RXCHAR);
if (Status == FALSE)
{
printf_s("\nError to in Setting CommMask\n\n");
}
//Setting WaitComm() Event
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
if (Status == FALSE)
{
printf_s("\nError! in Setting WaitCommEvent()\n\n");
}
//Read data and store in a buffer
do
{
Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
SerialBuffer[loop] = ReadData;
++loop;
} while (NoBytesRead > 0);
--loop; //Get Actual length of received data
printf_s("\nNumber of bytes received = %d\n\n", loop);
//print receive data on console
printf_s("\n\n");
int index = 0;
for (index = 0; index < loop; ++index)
{
printf_s("%d ", SerialBuffer[index]);
}
printf_s("\n\n");
CloseHandle(hComm);//Closing the Serial Port
return 0;
}

Multiclient pipe connection?

Is it possible to create a multiclient pipe? With one server and multiple clients? From the official documentation I have read that " A pipe server could use a single pipe instance to connect with multiple pipe clients by connecting to and disconnecting from each client in sequence, but performance would be poor" ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa365594(v=vs.85).aspx ). Is this behaviour standard (can be done using some flags or something like that) or I have to implement this behaviour by myself? I have written a test with multiply clients, but when I trying to connect by the second client, I got error STATUS_PIPE_NOT_AVAILABLE.
There is my code, it quite big, but functions test_multiple_client and test_multiple_client2 is the same
void test_mutiple_client( PVOID arg )
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
IO_STATUS_BLOCK iosb;
HANDLE thread = 0, event = 0, client = 0;
NTSTATUS r;
CLIENT_ID id;
LARGE_INTEGER timeout;
ULONG i;
us.Buffer = pipename;
us.Length = sizeof pipename - 2;
us.MaximumLength = us.Length;
oa.Length = sizeof oa;
oa.RootDirectory = 0;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = 0;
oa.SecurityQualityOfService = 0;
r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);
r = NtOpenFile( &client, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0 );
ok(r == STATUS_SUCCESS, "return wrong %08lx\n", r);
dprintf("mc: client1 pipe created\n");
int thread_id = __sync_add_and_fetch(&g__clientsCounter, 1);
while (g__clientsCounter != 2);
dprintf("thread %d stated\n", thread_id);
r = NtReadFile( client, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
if (r == STATUS_PENDING)
r = NtWaitForSingleObject( event, TRUE, 0 );
ok (r == STATUS_SUCCESS, "read %ld returned %08lx\n", i, r);
ok (i == 13, "lol?????");
r = NtClose( client );
ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);
}
void test_mutiple_client2( PVOID arg )
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
IO_STATUS_BLOCK iosb;
HANDLE thread = 0, event = 0, client = 0;
NTSTATUS r;
CLIENT_ID id;
LARGE_INTEGER timeout;
ULONG i;
us.Buffer = pipename;
us.Length = sizeof pipename - 2;
us.MaximumLength = us.Length;
oa.Length = sizeof oa;
oa.RootDirectory = 0;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = 0;
oa.SecurityQualityOfService = 0;
r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);
r = NtOpenFile( &client, GENERIC_READ | GENERIC_WRITE, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, 0 );
ok(r == STATUS_SUCCESS, "return wrong %08lx\n", r);
dprintf("mc: client1 pipe created\n");
int thread_id = __sync_add_and_fetch(&g__clientsCounter, 1);
while (g__clientsCounter != 2);
dprintf("thread %d stated\n", thread_id);
r = NtReadFile( client, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
if (r == STATUS_PENDING)
r = NtWaitForSingleObject( event, TRUE, 0 );
ok (r == STATUS_SUCCESS, "read %ld returned %08lx\n", i, r);
ok (i == 13, "lol?????");
r = NtClose( client );
ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);
}
void test_multiple_connections( )
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING us;
IO_STATUS_BLOCK iosb;
HANDLE pipe = 0, thread = 0, event = 0;
NTSTATUS r;
CLIENT_ID id;
LARGE_INTEGER timeout;
ULONG i;
us.Buffer = pipename;
us.Length = sizeof pipename - 2;
us.MaximumLength = us.Length;
oa.Length = sizeof oa;
oa.RootDirectory = 0;
oa.ObjectName = &us;
oa.Attributes = OBJ_CASE_INSENSITIVE;
oa.SecurityDescriptor = 0;
oa.SecurityQualityOfService = 0;
timeout.QuadPart = -10000LL;
r = NtCreateNamedPipeFile( &pipe, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
&oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, TRUE,
TRUE, FALSE, /*Unlimited*/ -1, 0, 0, &timeout );
ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);
dprintf("mc: server pipe created\n");
r = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE,
NULL, 0, 0, &test_mutiple_client, NULL, &thread, &id );
ok( r == STATUS_SUCCESS, "failed to create thread\n" );
r = RtlCreateUserThread( NtCurrentProcess(), NULL, FALSE,
NULL, 0, 0, &test_mutiple_client2, NULL, &thread, &id );
ok( r == STATUS_SUCCESS, "failed to create thread\n" );
r = NtCreateEvent( &event, EVENT_ALL_ACCESS, NULL, NotificationEvent, 0 );
ok(r == STATUS_SUCCESS, "return wrong (%08lx)\n", r);
r = NtFsControlFile( pipe, event, 0, 0, &iosb, FSCTL_PIPE_LISTEN, 0, 0, 0, 0 );
if (r == STATUS_PENDING) {
dprintf("mc: pending\n");
r = NtWaitForSingleObject( event, TRUE, 0 );
}
ok( r == STATUS_SUCCESS, "failed to listen %08lx\n", r );
dprintf("mc: server pipe listen\n");
i = 13;
while (g__clientsCounter != 2);
dprintf("server started\n");
r = NtWriteFile( pipe, event, 0, 0, &iosb, &i, sizeof i, 0, 0 );
if (r == STATUS_PENDING)
r = NtWaitForSingleObject( event, TRUE, 0 );
ok (r == STATUS_SUCCESS, "write %ld returned %08lx\n", i, r);
dprintf("server write data\n");
r = NtClose( pipe );
ok( r == STATUS_SUCCESS, "return wrong %08lx\n", r);
}
The output is
mc: server pipe created
mc: pending
mc: server pipe listen
mc: client1 pipe created
478: return wrong c00000ac
mc: client1 pipe created
thread 2 stated
488: read 2013057864 returned c0000008
489: lol?????492: return wrong c0000008
server started
thread 1 stated
server write data
4 failed, 38 passed
I also have seen an answer of stack ( Number of Clients that can connect to a Named Pipe ) where mentioned that windows pipes can hold up to 256 clients

SSL_connect results in SSL_ERROR_SYSCALL with WSAENOTCONN on Windows

I try to set SSL connection on Windows with OpenSSL. My steps follow:
Create TCP socket BIO.
Connect to server with TCP.
Add this BIO to SSL instance.
Upgrade connection to SSL.
However, when I try to call SSL_connect with BIO that for sure recently connected to TCP socket, I receive SSL_ERROR_SYSCALL with WSAENOTCONN on Windows.
My code follows.
this->TcpSocket = BIO_new(BIO_s_connect());
BIO_set_nbio(this->TcpSocket, 1);
BIO_set_conn_hostname(this->TcpSocket, hostname);
BIO_set_conn_port(this->TcpSocket, port);
int connectionResult;
while ((connectionResult = BIO_do_connect(this->TcpSocket)) <= 0 && BIO_should_retry(this->TcpSocket))
{
auto retryType = BIO_retry_type(this->TcpSocket);
if (retryType & BIO_FLAGS_READ != 0
|| retryType & BIO_FLAGS_WRITE != 0)
{
auto handle = BIO_get_fd(this->TcpSocket, NULL);
fd_set handles;
handles.fd_count = 1;
handles.fd_array[0] = handle;
timeval timeout;
timeout.tv_sec = seconds;
timeout.tv_usec = 0;
if (retryType & BIO_FLAGS_READ != 0)
select(handle + 1, &handles, NULL, NULL, &timeout);
else
select(handle + 1, NULL, &handles, NULL, &timeout);
}
else
Thread::Sleep(50);
}
this->SslContext = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_verify(this->SslContext, SSL_VERIFY_NONE, NULL);
this->SslSocket = SSL_new(this->SslContext);
SSL_set_bio(this->SslSocket, this->TcpSocket, this->TcpSocket);
int sslConnectResult;
while ((sslConnectResult = SSL_connect(this->SslSocket)) == -1)
{
auto now = time(NULL);
int sslConnectErrorCode = SSL_get_error(this->SslSocket, sslConnectResult);
switch (sslConnectErrorCode)
{
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
if (now >= deadline)
throw SocketTimeoutException();
else
this->WaitForTcpSocket(deadline - now);
break;
case SSL_ERROR_SYSCALL:
{
auto err = GetLastError();
this->RaiseOpenSSLException();
}
break;
default:
this->RaiseOpenSSLException();
}
}
What is reason of the error? I understand that it means that client is disconnected from server. But I don't understand why. I have good Internet connection, and server also is stable, so it is unlikely that the reason in network connectivity.
Your TCP connect loop is not taking into account if BIO_do_connect() fails and BIO_should_retry() returns false. Your loop will stop in that condition and you will not have a connection, but you attempt to activate SSL anyway, which could cause the WSAENOTCONN error.
Try something more like this instead:
do
{
connectionResult = BIO_do_connect(this->TcpSocket);
if (connectionResult > 0)
break;
if (!BIO_should_retry(this->TcpSocket))
throw SocketException();
auto retryType = BIO_retry_type(this->TcpSocket);
if (retryType & (BIO_FLAGS_READ | BIO_FLAGS_WRITE))
{
auto handle = BIO_get_fd(this->TcpSocket, NULL);
fd_set handles;
FD_ZERO(&handles);
FD_SET(handle, &handles);
timeval timeout;
timeout.tv_sec = seconds;
timeout.tv_usec = 0;
if (retryType & BIO_FLAGS_READ)
selectResult = select(handle + 1, &handles, NULL, NULL, &timeout);
else
selectResult = select select(handle + 1, NULL, &handles, NULL, &timeout);
if (selectResult < 0)
throw SocketException();
if (selectResult == 0)
throw SocketTimeoutException();
}
else
Thread::Sleep(50);
}
while (true);