[systemd-devel] How to get systemd to leave a USB serial console session alone when hadware is pulled?

Kaz Kylheku kaz at kylheku.com
Wed May 15 21:19:38 PDT 2013


On Wed, 15 May 2013 23:48:04 -0400, Greg KH <greg at kroah.com> wrote:
> On Wed, May 15, 2013 at 04:32:12PM -0700, Kaz Kylheku wrote:
>>
>> Hi all,
>>
>> I have a system that is configured to have a ttyUSB0 as a console.
>>
>> To improve this, I patched the Linux kernel to create a cool feature:
>> when a USB Converter is removed, although the `/dev/ttyUSB<n>` entry
>> disappears, existing file descriptors which have that tty device open
>> are undisturbed. Processes that are blocked on a tty read do not so
>> much
>> as wake up. Writes go to the bit bucket. When hardware re-appears and
>> `/dev/ttyUSB<n>` comes back to life, those tty file descriptors are
>> re-attached, and I/O nicely resumes. (Even if different hardware is
>> plugged in: remove a PL2303 and plug in an FTDI, and your tty is
>> back.)
> 
> Where is this patch you have created? 

So far, on the hard drive of the development machine where I created
it.

> This isn't something you rally
> want to do, as plugging in a different tty device, you don't want to
> resume sending data to it without letting userspace know that something
> changed.

That's my problem; let me worry about that. I have already decided
that this is the best design.

(Would you say the same thing about a simple RS-232 cable?
This is for an embedded system. It's not uncommon in embedded systems
to have a serial console which consists of a three-pin header on
a circuit board: TX, RX and GND.  Nothing knows that the cable is
pulled or inserted, and there is no hardware handshaking.
I've gotten USB Serial to behave in the same way, essentially.

Furthermore, the special treatment applies ONLY to those USB
serial devices which are marked as consoles, not to all USB
serial devices.

For most non-console use cases, of course it is better to know that
the hardware is gone.)

> And why isn't userspace paying attention to the HANGUP signal we send
> it?

Userspace does pay attention to hangup. Hangup is still there, if
someone generates it. (I don't want that, obviously.)

The behavior I describe is what happens in test cases in the absence
of any interference from such hangups. ttyUSB0 is marked as a console.
No agetty is running on the port or anything. We do something like

   $ cat > /dev/ttyUSB0
   type away

and the characters are sent out through the serial adapter.
When we unplug it, cat keeps running, and whatever we type
goes to the bit bucket. Then when we plug the hardware
back in,  we can resume typing and the characters are
transmitted again. Very simple and ideal for an embedded console.

You can get the same functionality by exposing a few UART
pins. But what if for whatever reason you want to design a
production board that doesn't expose the UART, but only
USB ports?


>> What's wrecking things is systemd:
>>
>> 1. systemd does not serve up an `agetty` on the port,
>>   unless the hardware is already inserted before the system
>>   boots up.
> 
> That is as planned.
> 
>> 2. If  the hardware is pulled, then systemd kills the session.
>>   It kills agetty and all its progeny, whether there is a logged
>>   in shell session on the console or not.
> 
> systemd should kill the session, it is working correctly.

I obviously agree, but I would like some assistance in obtaining
a different behavior (which is entirely optional and non-default,
and may not even make it into systemd, outside of the locally
maintained fork in the embedded distro that I work with.)

Since I can unplug the USB cable and plug it back in such that the
open tty object in the kernel remains valid, and a session can
stay intact, it is counterproductive to be destroying it.

Destroying the session makes sense when its tty cannot possibly
come back.
 
>> 3. Thirdly, systemd will not serve up `agetty` when the hardware is
>>   re-inserted even if it previously started `agetty` on that port.
>>   It notices the removal, but not the reinsertion.
> 
> As you seem to have changed the kernel to not handle the reinsertion,
> how can it know this?

No, I enhanced the kernel to handle the re-insertion in a more graceful
way with regard to certain behaviors in the tty subsystem. In other
respects, everything else is the same. The same udev events are
still generated and so on. The /dev/ttyUSB* entry disappears while the
hardware is pulled out and reappears when it is re-inserted.
You cannot open new TTY's to the hardware while it is not there,
but of course you can dup the open descriptors and pass them
to forked children.

Moreover, above behavior 3 already exists without the patch.
In the unpatched system, systemd will not serve up agetty when
the hardware is plugged in after the system is booted up.

That does seem like a genuine bug.

>> How can we configure systemd not to kill the session if the tty device
>> is removed, but only to ensure that all console devices have
>> an agetty?
> 
> As you are doing something very dangerous and not at all recommended,
> you really are on your own here. 

Look, I'm an very experienced developer, kernel and otherwise.
I know the patch is my responsibility and that kernel changes
are dangerous and so on.

I just don't know the internals of systemd; so it would be nice to
have some pointers.

> You get to keep the pieces when it
> breaks down, sorry.

Can you at least tell me how to get agetty to start on a system
that does not have my patch, when a USB-Serial converter is
inserted which is marked as a console?

Thanks.


More information about the systemd-devel mailing list