macOS Cocoa app: Crash with unspecified error - objective-c

I have Status Bar Cocoa App that provides GUI with general information and preferences windows for my background running server. This server is implemented in C programming language and the only work it is doing now is simple echo to client.
Application has button that starts this server. When I press this button server starts and listens on randomly selected port. It works correctly, I can even restart server etc.
I start server using this code:
- (void) startServerInBackground: (server_t) serverFunc {
dispatch_queue_t server_dispatch_queue = dispatch_queue_create("click.remotely.Server", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(server_dispatch_queue, ^(void){
start_server(serverFunc, serverInfo);
/***
* dispatch_async(dispatch_get_main_queue(), ^(void){
* //Run UI Updates
* });
*/
});
}
The problem begins only when some client connects to the server.
I can connect using telnet 192.168.8.101 <PORT_NUMBER>. I can even talk to server and it replays correctly. Here the odd things happens!
When I try to open Status Bar Cocoa App I can get crashes like this:
1. No crash for very long time (client talking to server, restarting, switching windows and panes)
2. Get crash immediately after connecting client and selecting Status Bar Icon of App
3. Get crash some time later when I connect client, open Status Bar Icon, select some Menu Item and try to Open window.
4. The app can also crash a little later ex. not on first window opening but third, fourth or n-th window opening, button clicking.
Below screenshot shows how this nondeterministic looks
What causes the app to crash? How can I resolve this issue?
Here is my server loop in C
/**
* Function is looping infinitely and waiting
* for new incoming client connections.
* It handles connections one by one on the same thread.
*/
result_t iterative_stream_server_loop(server_info_t *server_info, connection_handler_t handle_connection) {
sock_fd_t cs_fd, ps_fd;
// get passive server socket
ps_fd = server_info_sock(server_info);
while(1) {
if(server_info_should_shut_down(server_info)) {
return CLOSED;
}
if(server_info_force_shut_down(server_info)) {
return FORCE_CLOSED;
}
// check to accept new connection on the main thread...
cs_fd = accept_new_connection(ps_fd);
if(cs_fd == FAILURE) {
fprintf(stderr, "accept_new_connection: failed!\n");
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_ACCEPT, "accept_new_connection: failed!");
return FAILURE;
} else if(cs_fd == CONTINUE) {
continue;
}
// publish client connected event
server_info_client_connected_event(server_info, cs_fd);
printf("Handle connection on the main thread...\n");
switch (handle_connection(server_info, cs_fd)) {
case FAILURE:
fprintf(stderr, "handle_connection: failed!\n");
// publish connection error event
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_HANDLER, "handle_connection: failed!");
break;
case CLOSED:
printf("handle_connection: closed!\n");
// publish client disconnecting event
server_info_client_disconnecting_event(server_info, cs_fd);
break;
default:
break;
}
if(close(cs_fd) < 0){
fprintf(stderr, "close: %s\n", strerror(errno));
server_info_connection_error_event(server_info, cs_fd, CONN_ERROR_CLOSE, strerror(errno));
return FAILURE;
}
}
}
And here is the client connection handling (echo service)
result_t echo_service_connection_handler(server_info_t *server_info, sock_fd_t sock_fd) {
char buf[MAX_BUF_SIZE];
int n_recv; // number of bytes received
int n_sent; // number of bytes sent
fcntl(sock_fd, F_SETFL, O_NONBLOCK);
while(1) {
if(server_info_should_shut_down(server_info))
return CLOSED;
if ((n_recv = recv(sock_fd, buf, sizeof(buf) - 1, 0)) <= 0) {
if(n_recv == 0) {
printf("echo connection is closing...\n");
return CLOSED;
}
if( (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
// call to recv() on non-blocking socket result with nothing to receive
continue;
}
perror("recv");
// publish connection error event
server_info_connection_error_event(server_info, sock_fd, CONN_ERROR_RECV, strerror(errno));
return FAILURE;
}
buf[n_recv] = '\0';
printf(ANSI_COLOR_BLUE "server: received '%s'" ANSI_COLOR_RESET "\n", buf);
if ((n_sent = send(sock_fd, buf, strlen(buf), 0)) < 0) {
perror("send");
// publish connection error event
server_info_connection_error_event(server_info, sock_fd, CONN_ERROR_SEND, strerror(errno));
return FAILURE;
}
}
return SUCCESS;
}

Related

LUFA XInput Controller Endpoint IN/OUT not working

Intro:
I've been trying (and failing for four entire days straight so far) to get my Atmega32u4 device (Arduino Pro Micro) to emulate an Xbox controller.
It doesn't have to pretend it's an Xbox controller, but I need to communicate with the XInput driver, so emulating an official controller seemed like the best way to start.
The problem:
When using the code example XInputPadMicro by Bootsector it gets me exactly halfway. My device can either read OR write from/to the device driver. But not both. Getting both to work is essential to my project.
The code:
Device/Configuration descriptor can be found in XInputPadMicro (I
haven't changed these).
Configuration changed event:
Enabling the "OUT" endpoint will break the "IN" endpoint.
#define JOYSTICK_EPADDR_IN (ENDPOINT_DIR_IN | 1)
#define JOYSTICK_EPADDR_OUT (ENDPOINT_DIR_OUT | 1)
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_IN, EP_TYPE_INTERRUPT, 20, 1);
//If I enable this, the "IN" Endpoint will stop sending data.
//ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_OUT, EP_TYPE_INTERRUPT, 8, 1);
}
USB control request event:
void EVENT_USB_Device_ControlRequest(void)
{
/* Handle HID Class specific requests */
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(&gamepad_state, 20);
Endpoint_ClearIN();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(&RXData, 8);
Endpoint_ClearOUT();
}
break;
}
}
HID Task (called every cycle):
void HID_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_OUT);
if (Endpoint_IsOUTReceived())
{
toggle = !toggle;
SetLED(LED3, toggle);
Endpoint_Read_Stream_LE(&RXData, 8, NULL);
SetLED(LED1, RXData[3] > 0 || RXData[4] > 0);
Endpoint_ClearOUT();
}
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_IN);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&gamepad_state, 20, NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
}
Am I missing something crucial? Perhaps about the inner workings of the USB protocol? I am at a loss here.

Communicating dsPIC with PC application through UART. Receiver interrupt handling

I'm communicating my C# applications with dsPIC x16 microcontroller using UART. I want to send/receive fixed size frames and I tried to manage it in a following way:
if(readFrame)
{ IEC0bits.U1RXIE=0; //turn off the U1RX interrupts
readFrame = false;
while(indexer < 8 )
{
while(!U1STAbits.URXDA);
modbusBuffer[indexer]=U1RXREG;
indexer++;
}
if(indexer == 8)
{
modbusRecvTask(modbusBuffer);
indexer=0;
}
IEC0bits.U1RXIE=1; //turn on U1RX interrupts
}
void _ISR_NAP _U1RXInterrupt()
{
if(IFS0bits.U1RXIF)
{
IFS0bits.U1RXIF = 0; //set the interrupt flag to false
if(U1STAbits.OERR==1) //check overload error
{
U1STAbits.OERR=0; //clear error flag
}
else
{
readFrame = true;
}
}
}
The thing is that it works fine only for the first received frame. After that the program goes into the receiver interrupt again and sets the flag readFrame to true even though no bytes were send and is getting stuck in line:
while(!U1STAbits.URXDA);
I've read some advices to clear the read buffer of the UART in order to prevent the program to go into the ISR again but I couldn't find a way to do it.

How do I send strings between my osx app and arduino continuously?

I made a cocoa application that generates a list of instructions for an arduino uno to execute. Because the list is too large to fit at one time within the arduino's memory, I am trying to send the arduino an individual instruction at a time.
Arduino:
void setup(){
Serial.begin(9600);
}
void loop(){
if(Serial.available() > 0){
String in = Serial.readString();
delay(10);
Serial.print(in);
}
Serial.print("A");
}
Cocoa App
(Code after the serial port is open and working)
- (void)incomingTextUpdateThread: (NSThread *) parentThread {
// mark that the thread is running
readThreadRunning = TRUE;
const int BUFFER_SIZE = 1;
char byte_buffer[BUFFER_SIZE]; // buffer for holding incoming data
long numBytes=0; // number of bytes read during read
// assign a high priority to this thread
[NSThread setThreadPriority:1.0];
// this will loop unitl the serial port closes
while(TRUE) {
// read() blocks until some data is available or the port is closed
numBytes = read(serialFileDescriptor, byte_buffer, BUFFER_SIZE); // read up to the size of the buffer
if(numBytes>0) {
if(byte_buffer[0] == 'A'){
Coordinate *c = [coordinates objectAtIndex:coordinateIndex];
[self writeString:[self formateCoordinateString:c]];
coordinateIndex++;
}
}
if(coordinateIndex == coordinates.count){
close(serialFileDescriptor);
break;
}
}
readThreadRunning = FALSE;
}
I run the arduino code first and it prints a bunch of 'A's in the serial console. However once I start the cocoa app, it stops printing 'A's and doesn't do anything.
When I set a breakpoint within the while loop, the arduino starts printing the 'A's again. I continue to step within the while loop, and the "instruction" string is sent correctly to the arduino.
My issue is that this only works when I set this break point. Otherwise both my cocoa app and arduino app go into a stand-still.
Thanks for any and all advice! Please feel free to ask for clarification.

How to make an Attended call transfer with UCMA

I'm struggling with making a call transfer in a UMCA IVR app I've built. This is not using Lync.
Essentially, I have an established call from an outside user and as part of the IVR application, they select an option to be transferred. This transfer is to a configured outside number (ie: Our Live Operator). What I want to do is transfer the original caller to the outside number, and if a valid transfer is established, I want to terminate the original call. If the transfer isn't established, I want to send control back to the IVR application to handle this gracefully.
My problem is my EndTransferCall doesn't get hit when the transfer is established. I would have expected it to hit, set my AutoResetEvent and return a True, and then in my application I can disconnect the original call. Can somebody tell me what I'm missing here?
_call is an established AudioVideoCall. My application calls the Transfer method
private AutoResetEvent _waitForTransferComplete = new AutoResetEvent(false);
public override bool Transfer(string number, int retries = 3)
{
var success = false;
var attempt = 0;
CallTransferOptions transferOptions = new CallTransferOptions(CallTransferType.Attended);
while ((attempt < retries) && (success == false))
{
try
{
attempt++;
_call.BeginTransfer(number, transferOptions, EndTransferCall, null);
// Wait for the transfer to complete
_waitForTransferComplete.WaitOne();
success = true;
}
catch (Exception)
{
//TODO: Log that the transfer failed
//TODO: Find out what exceptions get thrown and catch the specific ones
}
}
return success;
}
private void EndTransferCall(IAsyncResult ar)
{
try
{
_call.EndTransfer(ar);
}
catch (OperationFailureException opFailEx)
{
Console.WriteLine(opFailEx.ToString());
}
catch (RealTimeException realTimeEx)
{
Console.WriteLine(realTimeEx.ToString());
}
finally
{
_waitForTransferComplete.Set();
}
}
Is the behavior the same if you don't use the _waitForTransferComplete object? You shouldn't need it - it should be fine that the method ends, the event will still be raised. If you're forcing synchronous behavoir in order to fit in with the rest of the application though, try it like this:
_call.EndTransfer(
_call.BeginTransfer (number,transferOptions,null,null)
);
I'm just wondering if the waiting like that causes a problem if running on a single thread or something...

non-blocking file openat()

I would like to implement a multi-threaded, non-blocking file open. Ideally, the desired solution would be to make a call to open() & have it return immediately, and do something like register a callback to be called (or handle a signal, or conditional variable) when the open() operation is actually complete. To that end, I wrote a little test driver that creates multiple simultaneous threads and tries to open the same file. I would have hoped the return from openat() to be an invalid file descriptor, with an errno == EAGAIN, but the open call seems to always block until the open completes successfully.
Is there an implementation of this approach for a non-blocking open()?
Thanks in advance.
Reference Thread Code:
void* OpenHandler(void* args)
{
// Declarations removed
Dir = "/SomeDir";
if ((DirFd = open(Dir, O_RDONLY )) < 0) {
printf("********Error opening Directory*******\n");
return NULL;
}
do {
FileFd = openat(DirFd, &FileName[DirLen], O_RDONLY | O_NONBLOCK);
/* If open failed */
if (FileFd == -1) {
if (errno == EAGAIN)
printf("Open would block\n");
else {
printf("Open failed\n");
pthread_exit(NULL);
}
}
else
Opened = 1;
} while (!Opened);
pthread_exit(NULL);
}
open() and openat() always fully resolve the open request in one shot (normally, this doesn't need to sleep, but it can if directory entries need to be brought in from disk or over the network).
To do what you want, you'll have to build a thread pool of file-opening threads, that perform the open() on behalf of the thread you want to continue working and notify it when the open is complete. Unless you're opening a lot of files on very slow network filesystems, I doubt the juice will be worth the squeeze.