Question

I have a Pseudo-terminal slave that's giving me a read/write error of Resource Temporarily Unavailable (11). I have been unable to solve this problem, but up until a week ago I didn't know anything pty's. So, I might be missing something obvious.

From what I have read, this can be caused by calling read() on a non-blocking pty. However, when I check the F_GETFL after I open() the slave pty, the value shows that it is a blocking file descriptor.

The output of F_GETFL shows that the O_NONBLOCK flag is disabled, and the O_RDWR flag is enabled:

printf("F_GETFL: %x\n", fcntl( slavefd, F_GETFL)); // outputs F_GETFL: 2

I have even tried treating slavefd as a non-blocking file by using select() to determine when it's ready. But, it just times out every time.

So, why does read() set errno to Resource Temporarily Unavailable if slavefd is set to blocking? Do the flags of F_GETFL look correct? What else can I try to narrow the cause of this problem?

Update: (more info)

I'm not sure yet, but I think the pty slave device node is being locked somehow by pppd. I have been told that you can echo into pty slave, which seems to be true except when pppd is using it.

Update 2: (code added)

if (argc!=2)
    return;

printf("opening %s\n", argv[1]);
slavefd = open(argv[1], O_RDWR );
if (slavefd < 0)
    return;

This update shows how I'm opening the slave device. Since I am using this application for debugging, I'm just directly using argv[1].

PROBLEM SOLVED:

The slave node that I was attempting to read/write to was being modified by pppd. When pppd takes control of a tty/pty device, it changes the line discipline from N_TTY to N_PPP. This means that when when you open() and then read() or write() to the slave node, the PPP intermediate driver is being used instead of the TTY driver. So, a read() and write() boils down to a totally different function. Looking at the N_PPP driver I found the following. This answers my question as to why EAGAIN was being returned.

/*
 * Read does nothing - no data is ever available this way.
 * Pppd reads and writes packets via /dev/ppp instead.
 */
static ssize_t
ppp_asynctty_read(struct tty_struct *tty, struct file *file,
          unsigned char __user *buf, size_t count)
{
    return -EAGAIN;
}

/*
 * Write on the tty does nothing, the packets all come in
 * from the ppp generic stuff.
 */
static ssize_t
        ppp_asynctty_write(struct tty_struct *tty, struct file *file,
           const unsigned char *buf, size_t count)
{
    return -EAGAIN;
}
Was it helpful?

Solution

The slave node that I was attempting to read/write to was being modified by pppd. When pppd takes control of a tty/pty device, it changes the line discipline from N_TTY to N_PPP. This means that when when you open() and then read() or write() to the slave node, the PPP intermediate driver is being used instead of the TTY driver. So, a read() and write() boils down to a totally different function. Looking at the N_PPP driver I found the following. This answers my question as to why EAGAIN was being returned.

/*
 * Read does nothing - no data is ever available this way.
 * Pppd reads and writes packets via /dev/ppp instead.
 */
static ssize_t
ppp_asynctty_read(struct tty_struct *tty, struct file *file,
          unsigned char __user *buf, size_t count)
{
    return -EAGAIN;
}

/*
 * Write on the tty does nothing, the packets all come in
 * from the ppp generic stuff.
 */
static ssize_t
        ppp_asynctty_write(struct tty_struct *tty, struct file *file,
           const unsigned char *buf, size_t count)
{
    return -EAGAIN;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top