Application crashed after calling function socket send

We have multi platform voip application. For this reason we use basic sockets in C++ (the same implementation for ios, android, linux). One thread reads data from socket and another is used for writing data to socket. Sometimes ios application crash without any crash logs. I localized problem with sockets. if socket is closed on the network or another problem is occured, the function recv return -1. It is ok. But if in the same time another thread call send, application will crash.

I made simple test example:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
static int socketID = -1;
void * ipThread( void *ptr )
{
int bytesRead = 1;
unsigned char pData [1000];
while (bytesRead > 0)
{

bytesRead = (int)recv( socketID, pData, sizeof(pData), 0 );
printf("testNetwork = Data socket: %d\n",bytesRead);
}

{
int bytesSent = (int)send( socketID, pData, 1000, 0 );
printf("testNetwork - Data send to socket: %d\n",bytesSent);
}
shutdown( socketID, SHUT_RDWR );
close( socketID );
socketID = -1;
return NULL;
}
void testNetwork()
{
printf("testNetwork - start\n");
if (socketID != -1)
{
printf("testNetwork - socket exist\n");
unsigned char pData [1000];
int bytesSent = (int)send( socketID, pData, 1000, 0 );
printf("testNetwork - Data send to socket: %d\n",bytesSent);
return;
}
char pIP[] ="yor ip server";
char pPort[] ="5010";

struct addrinfo* ai;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

int err = getaddrinfo(pIP, pPort, &hints, &ai);
if (err != 0)
{
printf("testNetwork - Error getaddrinfo: %d\n",err);
return;
}

socketID = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (socketID <= 0)
{
freeaddrinfo(ai);
printf("testNetwork - Error socket: %d\n",err);
return;
}

int status = connect(socketID, ai->ai_addr, ai->ai_addrlen);
freeaddrinfo(ai);
if (status != 0)
{
socketID = -1;
printf("testNetwork - Error socket: %d\n",err);
return;
}

pthread_t tid; // thread ID
pthread_attr_t attr; // thread attribute


pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, ipThread, NULL);
pthread_attr_destroy(&attr);
}

console output:

testNetwork - start
testNetwork = Data socket: 75
testNetwork = Data socket: -1

and application crashed with call stack in debug window:

Thread 1 Queue : com.apple.main-thread (serial)
#0 0x0000000183fd3de8 in mach_msg_trap ()
#1 0x0000000183fd3c60 in mach_msg ()
#2 0x0000000184516e40 in __CFRunLoopServiceMachPort ()
#3 0x0000000184514908 in __CFRunLoopRun ()
#4 0x0000000184434da8 in CFRunLoopRunSpecific ()
#5 0x000000018641a020 in GSEventRunModal ()
#6 0x000000018e454758 in UIApplicationMain ()
#7 0x000000010053d664 in main

#8 0x0000000183ec5fc0 in start ()

The send function does not exit with current value -1.


the same test on android is corrent. output console is:

testNetwork - start
testNetwork = Data socket: 75
testNetwork = Data socket: -1

testNetwork - Data send to socket: -1

the send funcion return corrent value -1.


Is it possible to set some socket option or something else to get expected result without crash? Thanks.

Accepted Reply

It sounds like you’re not handling

SIGPIPE
. A standard part of BSD Sockets is that writes to a closed socket will generate a
SIGPIPE
rather than return an error. BSD Sockets code must either or suppress that signal. This is not specific to Apple platforms; any standard BSD Sockets implementation will work this way.

One nice addition on Apple platforms is the

SO_NOSIGPIPE
socket option. This allows you to suppress
SIGPIPE
generation on a specific socket.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

It sounds like you’re not handling

SIGPIPE
. A standard part of BSD Sockets is that writes to a closed socket will generate a
SIGPIPE
rather than return an error. BSD Sockets code must either or suppress that signal. This is not specific to Apple platforms; any standard BSD Sockets implementation will work this way.

One nice addition on Apple platforms is the

SO_NOSIGPIPE
socket option. This allows you to suppress
SIGPIPE
generation on a specific socket.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"