Topics

C++ TCP code differences Pi-3 to Pi-4?


Larry K8UT
 

Three years ago I wrote a Band Decoder freeware app that communicates using TCP packets between a Windows GUI console and a Raspberry Pi CLI controller. Has been working fine here and at a few dozen QTHs around the world. I recently designed a miniature RPi HAT board with 16 opto-MOSFET "relay" outputs, replacing the original design of 2 x 8 SainSmart relay boards.

The HAT board works on both Pi-3 and Pi-4 hardware, but on an Pi-4_8gb (my only model 4) the Pi Controller software receives an initial TCP packet from the Console and thereafter refuses to accept additional packets with an "Error on accept" at this line of C++ code:

newsockfd = accept(localSocket, (struct sockaddr *) &cliaddr, &clilen);

Any advice or suggestions on further troubleshooting would be appreciated.

-larry (K8UT)


Eric
 

Hmmmm...just a guess...are you trying to use accept on the connection when it's already open?

Eric

On Mon, Sep 7, 2020 at 4:48 AM Larry K8UT <K8UT@...> wrote:
Three years ago I wrote a Band Decoder freeware app that communicates using TCP packets between a Windows GUI console and a Raspberry Pi CLI controller. Has been working fine here and at a few dozen QTHs around the world. I recently designed a miniature RPi HAT board with 16 opto-MOSFET "relay" outputs, replacing the original design of 2 x 8 SainSmart relay boards.

The HAT board works on both Pi-3 and Pi-4 hardware, but on an Pi-4_8gb (my only model 4) the Pi Controller software receives an initial TCP packet from the Console and thereafter refuses to accept additional packets with an "Error on accept" at this line of C++ code:

newsockfd = accept(localSocket, (struct sockaddr *) &cliaddr, &clilen);

Any advice or suggestions on further troubleshooting would be appreciated.

-larry (K8UT)


Larry K8UT
 

Thanks, Eric - I wish it were that simple. Yes, the connection is closed at the end of the previous loop.

The curious part is that on a Pi-3 this runs fine; but on an Pi-4 the exact some code fails.


Eric
 

is the accept blocking or non-blocking?  

Eric

On Mon, Sep 7, 2020 at 6:04 PM Larry K8UT <K8UT@...> wrote:
Thanks, Eric - I wish it were that simple. Yes, the connection is closed at the end of the previous loop.

The curious part is that on a Pi-3 this runs fine; but on an Pi-4 the exact some code fails.


N5XMT
 

Pi4 uses a VL805 USB controller and interfaces to the MCU via PCI-e  could that be the issue?

On Sep 7, 2020, at 18:04, Larry K8UT <k8ut@...> wrote:
Thanks, Eric - I wish it were that simple. Yes, the connection is closed at the end of the previous loop.

The curious part is that on a Pi-3 this runs fine; but on an Pi-4 the exact some code fails.


Folkert van Heusden
 

Have you done:
- strace
- tcpdump
- shared your code so others can take a look

On Mon, Sep 07, 2020 at 05:57:10PM -0700, Larry K8UT wrote:
Thanks, Eric - I wish it were that simple. Yes, the connection is closed at the end of the previous loop.

The curious part is that on a Pi-3 this runs fine; but on an Pi-4 the exact some code fails.


Larry K8UT
 

Thanks for the hints and suggestions. On a whim, I loaded a microSD card with the beta Raspberry Pi 64 bit OS and ... it works! Fearing my success was a fluke, I loaded/reloaded microSD cards with production 32 bit versions and beta 64 bit versions, inserting them in 2gb and 8gb Pi-4 hardware. Identical results in all tests: 32 bit platform fails at socket Accept stage; 64 bit succeeds.

Here's the code. Works on 32 bit Pi-3, on 64 bit Pi-4; not on 32 bit Pi-4:
//----- get TCP Packet String from CLIENT console-----------------------
string getTcpPacketString(int localSocket ) {
 
socklen_t clilen;
struct sockaddr_in cliaddr;
int newsockfd;
 
signal(SIGCHLD, SIG_IGN);// delete zombie fork processes
// waiting for poll()
int pResult = poll(fds, nfds, timeout);
if ( pResult == -1 ) { error("ERROR on socket poll()\n"); }
if ( pResult == 0 ) { usleep(10000); return ""; } // no client connected during this cycle
 
    newsockfd = accept(localSocket, (struct sockaddr *) &cliaddr, &clilen);
    if (newsockfd < 0) {
cout << "Error on accept..." << endl;
usleep(10000);
return "-1";
//error("ERROR on accept");
}
uint maxPacketSize = 2048;
char packet_data[maxPacketSize];
memcpy(packet_data, "\0", maxPacketSize);
 
uint received_bytes = read( newsockfd, packet_data, maxPacketSize);
if (received_bytes < 0) { error("ERROR reading from socket"); }
 
string localString(packet_data);
localString = localString.substr(0, received_bytes); 
// return a substring, else that entire DIM size is returned with trailing random chars
 
close(newsockfd);
return localString;
} // end getTcpPacketString ------------------------------------------
 


Bernard Littau
 

Hi Larry,

Change your use of accept to accept(localSocket, NULL,NULL); and remove all the client addr and len stuff. 

I think you are getting stack garbage in your clilen parameter that is causing accept to fail.  Since you are not using the return values just get rid of them.  

Bernard
KE7FEQ 

On Wed, Sep 9, 2020 at 02:49 Larry K8UT <K8UT@...> wrote:
Thanks for the hints and suggestions. On a whim, I loaded a microSD card with the beta Raspberry Pi 64 bit OS and ... it works! Fearing my success was a fluke, I loaded/reloaded microSD cards with production 32 bit versions and beta 64 bit versions, inserting them in 2gb and 8gb Pi-4 hardware. Identical results in all tests: 32 bit platform fails at socket Accept stage; 64 bit succeeds.

Here's the code. Works on 32 bit Pi-3, on 64 bit Pi-4; not on 32 bit Pi-4:


//----- get TCP Packet String from CLIENT console-----------------------


string getTcpPacketString(int localSocket ) {


 


socklen_t clilen;


struct sockaddr_in cliaddr;


int newsockfd;


 


signal(SIGCHLD, SIG_IGN);// delete zombie fork processes


// waiting for poll()


int pResult = poll(fds, nfds, timeout);


if ( pResult == -1 ) { error("ERROR on socket poll()\n"); }


if ( pResult == 0 ) { usleep(10000); return ""; } // no client connected during this cycle


 


    newsockfd = accept(localSocket, (struct sockaddr *) &cliaddr, &clilen);


    if (newsockfd < 0) {


cout << "Error on accept..." << endl;


usleep(10000);


return "-1";


//error("ERROR on accept");


}


uint maxPacketSize = 2048;


char packet_data[maxPacketSize];


memcpy(packet_data, "\0", maxPacketSize);


 


uint received_bytes = read( newsockfd, packet_data, maxPacketSize);


if (received_bytes < 0) { error("ERROR reading from socket"); }


 


string localString(packet_data);


localString = localString.substr(0, received_bytes); 


// return a substring, else that entire DIM size is returned with trailing random chars


 


close(newsockfd);


return localString;


} // end getTcpPacketString ------------------------------------------


 









Eric
 

What is the value of errno after the failed accept?   When you get the value of errno, you can look it up in errno.h to find the meaning.

Eric

On Wed, Sep 9, 2020, 02:49 Larry K8UT <K8UT@...> wrote:
Thanks for the hints and suggestions. On a whim, I loaded a microSD card with the beta Raspberry Pi 64 bit OS and ... it works! Fearing my success was a fluke, I loaded/reloaded microSD cards with production 32 bit versions and beta 64 bit versions, inserting them in 2gb and 8gb Pi-4 hardware. Identical results in all tests: 32 bit platform fails at socket Accept stage; 64 bit succeeds.

Here's the code. Works on 32 bit Pi-3, on 64 bit Pi-4; not on 32 bit Pi-4:
//----- get TCP Packet String from CLIENT console-----------------------
string getTcpPacketString(int localSocket ) {
 
socklen_t clilen;
struct sockaddr_in cliaddr;
int newsockfd;
 
signal(SIGCHLD, SIG_IGN);// delete zombie fork processes
// waiting for poll()
int pResult = poll(fds, nfds, timeout);
if ( pResult == -1 ) { error("ERROR on socket poll()\n"); }
if ( pResult == 0 ) { usleep(10000); return ""; } // no client connected during this cycle
 
    newsockfd = accept(localSocket, (struct sockaddr *) &cliaddr, &clilen);
    if (newsockfd < 0) {
cout << "Error on accept..." << endl;
usleep(10000);
return "-1";
//error("ERROR on accept");
}
uint maxPacketSize = 2048;
char packet_data[maxPacketSize];
memcpy(packet_data, "\0", maxPacketSize);
 
uint received_bytes = read( newsockfd, packet_data, maxPacketSize);
if (received_bytes < 0) { error("ERROR reading from socket"); }
 
string localString(packet_data);
localString = localString.substr(0, received_bytes); 
// return a substring, else that entire DIM size is returned with trailing random chars
 
close(newsockfd);
return localString;
} // end getTcpPacketString ------------------------------------------
 


Larry K8UT
 

Bernard - That did it! THANK YOU!

I am embarrassed to admit how many hours I spent trying to solve this problem. Your fix enables users to select the hardware of their choice.

Thanks again!