[PD] preventing comport freezes

Hans-Christoph Steiner hans at at.or.at
Fri May 15 06:14:27 CEST 2009


On May 14, 2009, at 6:56 PM, Martin Peach wrote:

> Hans-Christoph Steiner wrote:
>> On May 9, 2009, at 2:43 PM, Martin Peach wrote:
>>> Roman Haefeli wrote:
>>>> thanks for the info.
>>>> On Fri, 2009-05-08 at 19:27 +0000, martin.peach at sympatico.ca wrote:
>>>>>> just out of curiosity: if there is a solution, that works well  
>>>>>> for
>>>>>> [tcpserver], couldn't it be applied also to [comport]?
>>>>>>
>>>>> Maybe. But I think you should be able to use [comport] with no
>>>>> hardware handshaking enabled and send data even if no cable is
>>>>> attached. Sometimes the absence of one of the two input handshake
>>>>> signals prevents the serial hardware from sending. Also if an  
>>>>> error
>>>>> occurred in the reception of serial data it may not be handled
>>>>> properly in [comport]. So I'm not sure what is causing this  
>>>>> particular
>>>>> crash, since HC said that it happened when the remote device was
>>>>> disconnected but gave no further detail.
>>>> iirc, on linux at least, [comport] makes pd hang, _whenever_ the  
>>>> other
>>>> end disappears. i.e.:
>>>> - pulling out the usb-cable, while the arduino is connected
>>>> - turning off an rfcomm device
>>>
>>>
>>> This looks like something related to the usb interface. I think  
>>> pulling out an RS-232 cable has no effect, as the serial driver  
>>> can only be closed by [comport]. With a usb adapter the usb driver  
>>> can close the port.
>>> I suspect that the comport_tick routine, which is called  
>>> periodically to check for received characters, tries to access the  
>>> serial port after the usb driver has closed it.
>>> The non-Windows code in comport_tick looks like this:
>>>
>>> unsigned char   serial_byte;
>>> fd_set          com_rfds;
>>> int             count = 0;
>>>
>>> FD_ZERO(&com_rfds);
>>> FD_SET(fd,&com_rfds);
>>>
>>> while((err=select(fd+1,&com_rfds,NULL,NULL,&null_tv)) > 0)
>>> {
>>>   err = read(fd,(char *) &serial_byte,1);
>>>   outlet_float(x->x_data_outlet, (t_float) serial_byte);
>>>   ++count;
>>> }
>>>
>>> As you can see the select call only checks for the presence of  
>>> received characters with com_rfds, and doesn't check the write or  
>>> exception status. I suppose the select call should also check the  
>>> exception fd_set, as the usb driver has no other way of informing  
>>> [comport] that it has closed the port, it should have flagged it  
>>> there.
>>> (Although if the fd itself is no longer valid I don't know what to  
>>> do...using non-existent file descriptors is a good way to crash Pd)
>>>
>>> ATM I only have 'legacy' RS-232 ports on my hardware so I can't  
>>> test it, but I can change the code.
>>>
>>> Martin
>> Ok, quick test shows a couple things:
>> - just using [comport 1 115200] and then yanking the USB out causes  
>> the crash, so no data needs to be sent to cause this.  This is with  
>> a standard Arduino USB.
>
> So the crash most likely occurs when comport_tick is called by the  
> timer.
>
>> - in the select() that you highlight, it is just testing before  
>> reading, so I am guessing it would not be so useful to do a write  
>> test if it is only going to read().
>
> The write test is not needed, but I was thinking that the third  
> possible test, the exception test, might give useful info, unless  
> the file descriptor has already become invalid, in which case I  
> don't know what to do about it, since using a dead file descriptor  
> is usually lethal and probably is what is causing the crash.
> How does [hid] react to unplugging of the device?

In [hid] I don't remember doing anything special, I never even used  
select(). I am guessing that serial ports behave differently that USB  
HID.  Serial was designed to be permanently attached, USB was designed  
to be hot-pluggable.   Here's the read() for example:

     while( read (x->x_fd, &(hid_input_event), sizeof(struct  
input_event)) > -1 )

I open it using read-only and non-blocking, maybe that has something  
to do with it?

	x->x_fd = open(block_device, O_RDONLY | O_NONBLOCK);

I just tried a test with just a USB serial adapter, it didn't actually  
crash, it just stopped responding and pegged the CPU.

.hc

----------------------------------------------------------------------------

There is no way to peace, peace is the way.       -A.J. Muste






More information about the Pd-list mailing list