[2.5] Non-blocking write can block

[2.5] Non-blocking write can block

Post by P. Beni » Thu, 05 Jun 2003 03:00:19



Non-blocking writes to a tty will block if there is a blocking write
waiting for the atomic_write semaphore.

Peter

--- linux-2.5.70/drivers/char/tty_io.c.orig     2003-06-03 21:34:42.000000000 +0100

 {
        ssize_t ret = 0, written = 0;

-       if (down_interruptible(&tty->atomic_write)) {
-               return -ERESTARTSYS;
+       if (file->f_flags & O_NONBLOCK) {
+               if (down_trylock(&tty->atomic_write))
+                       return -EAGAIN;
+       }
+       else {
+               if (down_interruptible(&tty->atomic_write))
+                       return -ERESTARTSYS;
        }
        if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) {
                lock_kernel();

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Christoph Hellwi » Thu, 05 Jun 2003 08:00:16



> -  if (down_interruptible(&tty->atomic_write)) {
> -          return -ERESTARTSYS;
> +  if (file->f_flags & O_NONBLOCK) {
> +          if (down_trylock(&tty->atomic_write))
> +                  return -EAGAIN;
> +  }
> +  else {

The else should be on the same line as the closing brace, else
the patch looks fine.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Linus Torvald » Thu, 05 Jun 2003 16:40:14



> The else should be on the same line as the closing brace, else
> the patch looks fine.

No no no, it's wrong.

If you do something like this, then you also have to teach "select()"
about this, otherwise you just get busy looping in applications.

In general, we shouldn't do this, unless somebody can show an application
where it really matters. Taking internal kernel locking into account for
"blockingness" easily gets quite complicated, and there is seldom any real
point to it.

Remember: perfect is the enemy of good. I'll happily apply the patch (if
it also updates the tty poll() functionality), _if_ there is some
real-world situation where it matters.

                Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by P. Beni » Thu, 05 Jun 2003 17:00:32



> No no no, it's wrong.

> If you do something like this, then you also have to teach "select()"
> about this, otherwise you just get busy looping in applications.

> In general, we shouldn't do this, unless somebody can show an application
> where it really matters.

I wrote the patch to solve a real-world problem with wall(1), which
occasionally gets stuck writing to somebody's tty. I think it's reasonable
for wall to assume that non-blocking writes are non-blocking.

I'll think about how to do the patch correctly.

Peter

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Timothy Mille » Thu, 05 Jun 2003 17:20:13




>>-       if (down_interruptible(&tty->atomic_write)) {
>>-               return -ERESTARTSYS;
>>+       if (file->f_flags & O_NONBLOCK) {
>>+               if (down_trylock(&tty->atomic_write))
>>+                       return -EAGAIN;
>>+       }
>>+       else {

> The else should be on the same line as the closing brace, else
> the patch looks fine.

I am in general agreement with those who feel we should have a common
standard for code formatting.  There are particular places where it's
VERY important to maximize consistency and readability, such as function
headers.

But when do standards turn into nitpicks?

I personally always write else as you suggest, "} else {", but the way
the other fellow did it does not in any way hurt readability for me.
Yes, it does irritate me sometimes when people put the braces and else
on three different lines, but mostly because it reduces the amount of
code I can see at one time.  But even then, it doesn't make it any less
readable to me.

I can see patches getting rejected because they violate function header
standards.  That would make sense to me.  But if the above patch were to
be rejected on the basis of the "else", I would be hard pressed to see
that as a valid justification.

Perhaps it would be good to have an explanation for the relative
importance of placing braces and else on the same line as compared to
other formatting standards.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Hua Zhon » Thu, 05 Jun 2003 19:20:26


We ran into this problem here in an embedded environment. It causes
syslogd to hang and when this happens, everybody who talks to syslogd
hangs. Which means you may not even be able to login. In the end we used
exactly the same fix which seems to work.

I am curious to know the correct fix.


> > The else should be on the same line as the closing brace, else
> > the patch looks fine.

> No no no, it's wrong.

> If you do something like this, then you also have to teach "select()"
> about this, otherwise you just get busy looping in applications.

> In general, we shouldn't do this, unless somebody can show an
> application
> where it really matters. Taking internal kernel locking into
> account for
> "blockingness" easily gets quite complicated, and there is
> seldom any real
> point to it.

> Remember: perfect is the enemy of good. I'll happily apply
> the patch (if
> it also updates the tty poll() functionality), _if_ there is some
> real-world situation where it matters.

>            Linus

> -
> To unsubscribe from this list: send the line "unsubscribe
> linux-kernel" in

> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
 
 
 

[2.5] Non-blocking write can block

Post by Alan Co » Thu, 05 Jun 2003 19:50:12



Quote:> In general, we shouldn't do this, unless somebody can show an application
> where it really matters. Taking internal kernel locking into account for
> "blockingness" easily gets quite complicated, and there is seldom any real
> point to it.

Hanging shutdown is the obvious one. With 2.0/2.2 we had a similar
problem and fixed it.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Linus Torvald » Thu, 05 Jun 2003 19:50:13



> We ran into this problem here in an embedded environment. It causes
> syslogd to hang and when this happens, everybody who talks to syslogd
> hangs. Which means you may not even be able to login. In the end we used
> exactly the same fix which seems to work.

> I am curious to know the correct fix.

[ First off: your embedded syslog problem is fixed by making sure that
  syslog doesn't try to write to a tty that somebody else might be
  blocked. In other words, to me it sounds like a "well, don't do that
  then" schenario, rather than a real kernel problem. ]

[ Secondly, you should all realize that O_NONBLOCK has _never_ meant that
  the IO can't ever block. Even O_NONBLOCK reads and writes will always
  block on things like having page faults on the user buffer, and a lot of
  drivers still use the kernel lock and will block on that. O_NONBLOCK is
  not an absolute "this is atomic" thing, it's a "don't wait for data if
  there is none" thing ]

With that in mind, if you feel strongly about this particular path, then I
can only warn you that the correct fix actually looks fairly hard, as far
as I can tell. Yes, the posted patch is a small part of it, but the more
complex side is how to make poll() agree with the write semantics that the
posted patch changed.

If you have a write() that returns -EAGAIN, and a poll() function that
says "it's ok to write", any select-loop based application will start
busy-looping calling poll/write, and use up 100% CPU time.

Which may be acceptable for some users, of course, but what you're doing
with the simple patch is just replacing one bug with another one. And I
personally think the bug you're introducing is the worse one.

But which bug you "prefer" ends up depending entirely on the machine load
and usage - the current behaviour has clearly not ended up in very many
complaints, and even if the patch fixes it for those few people didn't
like the historical behaviour, it may well end up breaking a hell of a lot
more distributions that until now were perfectly happy.

For example: what happens when your real-time application starts
busy-looping due to this?  Right. The system is totally _dead_, since the
application that is busy writing to the tty will never be scheduled.

And yes, something like syslogd could easily be marked high-priority in
some setup. You do NOT want to make it busy-loop.

As to how to expand the patch to avoid the busy-loop: it's definitely
non-trivial. Semaphores do not have poll() qualities, and I don't see a
good way to get them. Something like

   static unsigned int tty_poll(struct file * filp, poll_table * wait)
   {
        struct tty_struct * tty;
        struct semaphore *sem;
        int retval;

        tty = (struct tty_struct *)filp->private_data;
        if (tty_paranoia_check(tty, filp->f_dentry->d_inode->i_rdev, "tty_poll"))
                return 0;

        sem = &tty->atomic_write;
        if (!down_trylock(sem)) {
                poll_wait(filp, sem->wait, wait);
                if (!down_trylock(sem))
                        return 0;
        }
        retval = 0;
        if (tty->ldisc.poll)
                retval = tty->ldisc.poll(tty, filp, wait);
        up(sem);
        return retval;
   }

MIGHT work, but as you can see it actually now depends on knowing the
internals of the semaphore implementation, and quite frankly I don't know
if it works at all. As a result, I'm not horribly keen on the idea.

And as I tried to explain, I'm also not horribly keen on having a write()  
that doesn't match poll() and can cause busy looping.

                Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Mike Dresse » Thu, 05 Jun 2003 20:00:16



> We ran into this problem here in an embedded environment. It causes
> syslogd to hang and when this happens, everybody who talks to syslogd
> hangs. Which means you may not even be able to login. In the end we used
> exactly the same fix which seems to work.

I get this problem with writing to a remote syslog server, if the remote
syslog server hangs up or crashes no one can login to the machine that is
writing to the syslog server, even when the syslog server comes back.

Mike

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Linus Torvald » Thu, 05 Jun 2003 20:00:18




> > In general, we shouldn't do this, unless somebody can show an application
> > where it really matters. Taking internal kernel locking into account for
> > "blockingness" easily gets quite complicated, and there is seldom any real
> > point to it.

>* shutdown is the obvious one. With 2.0/2.2 we had a similar
> problem and fixed it.

As I tried to point out, the current patch on the table doesn't actually
"fix" anything, in that it can break things even _worse_ than the current
situation.

A much better fix might well be to actually not allow over-long tty writes
at all, and thus avoid the "block out" thing at the source of the problem,
instead of trying to make programs who play nice be the ones that suffer.

If somebody does a 1MB write to a tty, do we actually have any reason to
try to make it so damn atomic and not return early?

                Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://www.veryComputer.com/
Please read the FAQ at  http://www.veryComputer.com/

 
 
 

[2.5] Non-blocking write can block

Post by Hua Zhon » Thu, 05 Jun 2003 20:50:12


> -----Original Message-----

> Sent: Wednesday, June 04, 2003 10:42 AM
> To: Hua Zhong
> Cc: 'Christoph Hellwig'; 'P. Benie'; 'Kernel Mailing List'
> Subject: RE: [PATCH] [2.5] Non-blocking write can block


> > We ran into this problem here in an embedded environment. It causes
> > syslogd to hang and when this happens, everybody who talks to
syslogd
> > hangs. Which means you may not even be able to login. In the end we
> > used exactly the same fix which seems to work.

> > I am curious to know the correct fix.

> [ First off: your embedded syslog problem is fixed by making sure that
>   syslog doesn't try to write to a tty that somebody else might be
>   blocked. In other words, to me it sounds like a "well, don't do that
>   then" schenario, rather than a real kernel problem. ]

It's hard. The shell might be printing and you cannot prevent that.

That said, the main problem was somebody could be stuck in waiting for
tty *forever* and thus everyone who tries to write also hangs.

This particular patch is in 2.4.20 already. There is another patch in
2.4.20 (?) which seems to fix the "main problem" (the n_tty_write_wakeup
function in n_tty.c), but I didn't verify it.

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by P. Beni » Thu, 05 Jun 2003 20:50:13



> This particular patch is in 2.4.20 already. There is another patch in
> 2.4.20 (?) which seems to fix the "main problem" (the n_tty_write_wakeup
> function in n_tty.c), but I didn't verify it.

Yes - that's because I submitted the patch ages ago.  All that means is
that the distributions are relying on it, not that the patch is correct!

Peter

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

 
 
 

[2.5] Non-blocking write can block

Post by Ben Pfaf » Thu, 05 Jun 2003 21:20:11




> > We ran into this problem here in an embedded environment. It causes
> > syslogd to hang and when this happens, everybody who talks to syslogd
> > hangs. Which means you may not even be able to login. In the end we used
> > exactly the same fix which seems to work.

> > I am curious to know the correct fix.

> [ First off: your embedded syslog problem is fixed by making sure that
>   syslog doesn't try to write to a tty that somebody else might be
>   blocked. In other words, to me it sounds like a "well, don't do that
>   then" schenario, rather than a real kernel problem. ]

One day I managed to keep myself from logging in or su'ing or
doing a number of things that needed the log for a quite a while
by accidentally hitting Scroll Lock on a console that syslog was
set up to log to.  I suppose the answer is "don't do that" but it
was a mysterious problem for several minutes that day.
--
"Let others praise ancient times; I am glad I was born in these."
--Ovid (43 BC-18 AD)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in

More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/
 
 
 

1. Non blocking socket blocks; says 'read would block' ?

Hi all,

I have three sockets in server which I am reading in a continuous loop,
so don't want to wait on any one. I have designated them as 'non blocking'
but when run the server exits on the very first read() and says 'would
block'. (Is it the same as 'EWOULDBLOCK' mentioned in R. Steven's book ?)
I don't want that I should get any error msg and exit, in fact the
whole purpose of nonblocking is that if something is available, read it
else proceed in the loop and come back to read next time.
The client (sender) is sending msgs on all three sockets. The sockets
are conn_oriented. I am using SunOS 4.1. The small code part is below:

int emer_s, env_s, sens_s;            /* socket fds */
//----------- making sockets nonblocking ******
if ((res=fcntl(emer_s,F_SETFL,FNDELAY)) < 0)
        {
          perror("fcntl res = -1");
          exit(1);
        }
if ((res=fcntl(env_s,F_SETFL,FNDELAY)) < 0)
        {
          perror("fcntl res = -1");
          exit(1);
        }
if ((res=fcntl(sens_s,F_SETFL,FNDELAY)) < 0)
        {
          perror("fcntl res = -1");
          exit(1);
        }

for(; ;)
   {

      if ((cc=read(emer_s,(char*)&gen_struct,size)) < size)
        {
        perror("read error");
          exit(1);
        }
......... do something
      if ((cc=read(env_s,(char*)&gen_struct,size)) < size)
        {
         perror("read error");
          exit(1);
        }
        ......... do something
      if ((cc=read(sens_s,(char*)&gen_struct,size)) < size)
        {
          perror("read error");
          exit(1);
        }
        ......... do something

   }

Any help is appreciated.

hashmi

--
-----
Atiqullah Hashmi                    
UTA (Univ. of Texas at Arlington)  

2. Domain Name Resolution Problem

3. Problem : can't make pipe non-blocking on 2.5.X

4. TeleS 128 internet pnp useable?

5. Blocking connect() fails, non-blocking succeeds?

6. Linux and CDE?

7. Blocking and Non-Blocking socket

8. Kernel Panic during slackware installation - HELP

9. [2.2] pipe_write can block even with non-blocking fd

10. how to get blocking i/o after non-blocking???

11. Blocking & Non-Blocking

12. Non-blocking socket reads block! (Bug?)

13. Problem with blocking opens preventing non-blocking opens in AIX 5.2