Yes we have 10K pullups, which are a little on the low side but the signals look good at 100 kbits. Teensy2 does not hang in this way.
Oddly I just tried another Teensy3 module (my tech is working on the board and Teensy in use earlier) hooked to nothing and of course I don't see any I2C signals because it has no pullups. But it does fail with an error 4, which is "other error". At least it isn't a hang. This Teensy3 is at a different virtual COM port too... why is that? I guess one COM port for each Teensy serial number?
OK, I got another Teensy3 (COM 17) hooked up to nothing with pullups and it is failing but returning error 2, NAK on address, which is correct.
If I open the clock line, so no pullup any more, it hangs. The data line is high, and clock is floating/low.
So the problem is a little different than I first thought. It seems to be as you said, there is a wait forever if at least one of the lines is stuck low. This is harder to achieve with Teensy2 since it has the weak pullups built in.
In any case we don't ever want Teensy3 to hang. We will also have a watchdog, but this could just create an endless loop. We'd rather have Teensy return - if the bus is stuck, there's no value in waiting forever. We'd like to know there is an error, so that our code can try to send an alert and if necessary go to a fail safe mode.
Can this be easily done as a library change? Would Arduino want to incorporate it into their code?
This leads me to wonder if we should split our I2C devices across the alternate I2C pins (Teensy3 16 & 17) so that we might survive a partial sensor/control bus failure? This sort of exception handling is always tough.
Thanks for the helpful info. Could the lib be changed so that it does not wait forever but returns an error? Code 4 would be OK. Ideally there would be a "stuck bus" code, but maybe this happens so rarely it isn't useful information.
We had a peer TWI network on another project, with four nodes, on AVRs, and tested millions of messages and never saw an bus stuck error. That was all C code, not Arduino, and we never waited forever. A stuck bus would have broken the sensor/control data channel anyway but each node could go to a safe state.
There is an NXP app note about bidirectionally buffering and voltage-level isolating the I2C bus with a single N-FET such as BSS138, and in that case an unpowered node on one side doesn't hamper operation of the other, but it does nothing for a line stuck low. Maybe we isolate two groups of somewhat redundant sensors in hopes that at least half will work at all times if one part is unpowered. The unpowered portion would of course lose its pullups, so that needs to be considered.