Running the top in the stream gives SIGTTOU

For reasons that I will not go into, I need to run the "top -m io -d 2 10" option in a subprocess from the Python thread on FreeBSD 8.1. The trouble is that sometimes SIGTTOU is created (under certain code-dependent conditions that I have not yet decoded), completely closing the top and the thread. In other cases, it seems that SIGTTOU is not being produced, but the top or thread is stuck anyway.

The exit from the top should produce two sets of I / O characteristics for the first 10 processes in the system, where the first set is an β€œabsolute” number, and the second set is an incremental difference in statistics from the moment of the last set, one second earlier. Running this command on a terminal or in a shell script, whether redirecting output or not, works great.

When a problem occurs, it seems that "top" writes the first set of outputs, but then freezes / accepts SIGTTOU before it can output the second set. In the example below, only one set of process parameters is written to the output file.

I found a SIGTTOU signal that runs a python script under "truss", but it seems that the interactions between the "farm" and the "top" can be mixed, since a simple start truss top -d 2triggers a signal and freezes, as shown below:

...
ioctl(1,TIOCGETA,0xffffe460)             = 0 (0x0)
ioctl(1,TIOCGETA,0xc6b138)           = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe410)             = 0 (0x0)
ioctl(1,TIOCGWINSZ,0xffffe460)           = 0 (0x0)
ioctl(1,TIOCGWINSZ,0xffffe930)           = 0 (0x0)
ioctl(1,TIOCGETA,0x50e560)           = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGINT|SIGQUIT|SIGTSTP,0x0) = 0 (0x0)
ioctl(1,TIOCGETA,0x50e560)           = 0 (0x0)
SIGNAL 22 (SIGTTOU)

Here is an example Python script that reproduces a hang and / or SIGTTOU:

import subprocess
from threading import Thread

def run():
    with open("top.log", "wb") as f:
        subprocess.Popen(("/usr/bin/top", "-m", "io", "-d", "2", "10"), stdout=f, stderr=f, stdin=subprocess.PIPE).communicate()

if __name__ == "__main__":
    th = Thread(target=run)
    print "Starting"
    th.start()
    th.join()

During my last run, this sample program did not produce SIGTTOU, but the top hung. Truss shows:

....
open("/usr/local/lib/python2.7/lib-tk/_heapq.pyc",O_RDONLY,0666) ERR#2 'No such file or directory'
stat("/usr/local/lib/python2.7/lib-dynload/_heapq",0x7fffffffa500) ERR#2 'No such file or directory'
open("/usr/local/lib/python2.7/lib-dynload/_heapq.so",O_RDONLY,0666) = 5 (0x5)
fstat(5,{ mode=-rwxr-xr-x ,inode=238187,size=22293,blksize=16384 }) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
open("/usr/local/lib/python2.7/lib-dynload/_heapq.so",O_RDONLY,057) = 6 (0x6)
fstat(6,{ mode=-rwxr-xr-x ,inode=238187,size=22293,blksize=16384 }) = 0 (0x0)
pread(0x6,0x80074c2e0,0x1000,0x0,0xffff800800653120,0x8080808080808080) = 4096 (0x1000)
mmap(0x0,1069056,PROT_NONE,MAP_PRIVATE|MAP_ANON|MAP_NOCORE,-1,0x0) = 34389442560 (0x801c54000)
mmap(0x801c54000,12288,PROT_READ|PROT_EXEC,MAP_PRIVATE|MAP_FIXED|MAP_NOCORE,6,0x0) = 34389442560 (0x801c54000)
mmap(0x801d56000,12288,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,6,0x2000) = 34390499328 (0x801d56000)
mmap(0x0,36864,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34366377984 (0x800655000)
close(6)                     = 0 (0x0)
mmap(0x0,832,PROT_READ|PROT_WRITE,MAP_ANON,-1,0x0) = 34366414848 (0x80065e000)
munmap(0x80065e000,832)              = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGKILL|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
close(5)                     = 0 (0x0)
close(4)                     = 0 (0x0)
close(3)                     = 0 (0x0)
close(2)                     = 0 (0x0)
fstat(1,{ mode=crw------- ,inode=102,size=0,blksize=4096 }) = 0 (0x0)
ioctl(1,TIOCGETA,0xffffe400)             = 0 (0x0)
Starting
write(1,"Starting\n",9)              = 9 (0x9)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGKILL|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
_umtx_op(0x7fffffffe1d8,0x3,0x1,0x0,0x0,0x0)     = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGABRT|SIGEMT|SIGKILL|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2) = 0 (0x0)
sigprocmask(SIG_SETMASK,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGABRT|SIGEMT|SIGKILL|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2) = 0 (0x0)
sigprocmask(SIG_SETMASK,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
mmap(0x7fffffbde000,135168,PROT_READ|PROT_WRITE,MAP_STACK,-1,0x0) = 140737484021760 (0x7fffffbde000)
mprotect(0x7fffffbde000,4096,PROT_NONE)      = 0 (0x0)
thr_new(0x7fffffffe220,0x68,0x800a9f4c0,0x186fc,0xffffffff,0x0) = 0 (0x0)
sigprocmask(SIG_SETMASK,0x0,0x0)         = 0 (0x0)
mmap(0x0,2097152,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34390511616 (0x801d59000)
mmap(0x801f59000,684032,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANON,-1,0x0) = 34392608768 (0x801f59000)
munmap(0x801d59000,684032)           = 0 (0x0)
_umtx_op(0x8010127f8,0x10,0x1,0x0,0x0,0x0)   = 0 (0x0)
_umtx_op(0x800e0b438,0xf,0x0,0x0,0x0,0x0)    = 0 (0x0)
_umtx_op(0x800e0b438,0x10,0x1,0x0,0x0,0x0)   = 0 (0x0)
_umtx_op(0x800e0b438,0x10,0x1,0x0,0x0,0x0)   = 0 (0x0)
_umtx_op(0x800e0b438,0x10,0x1,0x0,0x0,0x8080808080808080) = 0 (0x0)
open("top.log",O_WRONLY|O_CREAT|O_TRUNC,0666)    = 2 (0x2)
fstat(2,{ mode=-rw-r--r-- ,inode=70860,size=0,blksize=16384 }) = 0 (0x0)
pipe(0x7fffffbfd910)                 = 0 (0x0)
pipe(0x7fffffbfd870)                 = 0 (0x0)
fcntl(6,F_GETFD,)                = 0 (0x0)
fcntl(6,F_SETFD,FD_CLOEXEC)          = 0 (0x0)
sigprocmask(SIG_BLOCK,SIGHUP|SIGINT|SIGQUIT|SIGABRT|SIGEMT|SIGKILL|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGSTOP|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2) = 0 (0x0)
fork()                       = 21503 (0x53ff)
sigprocmask(SIG_SETMASK,SIGHUP|SIGINT|SIGQUIT|SIGILL|SIGTRAP|SIGABRT|SIGEMT|SIGFPE|SIGBUS|SIGSEGV|SIGSYS|SIGPIPE|SIGALRM|SIGTERM|SIGURG|SIGTSTP|SIGCONT|SIGCHLD|SIGTTIN|SIGTTOU|SIGIO|SIGXCPU|SIGXFSZ|SIGVTALRM|SIGPROF|SIGWINCH|SIGINFO|SIGUSR1|SIGUSR2,0x0) = 0 (0x0)
close(6)                     = 0 (0x0)
close(3)                     = 0 (0x0)
read(5,0x801e31024,1048576)          = 0 (0x0)
close(5)                     = 0 (0x0)
fcntl(4,F_GETFL,)                = 2 (0x2)
fstat(4,{ mode=p--------- ,inode=0,size=0,blksize=4096 }) = 0 (0x0)
close(4)                     = 0 (0x0)

I looked into SIGTTOU and found links to the TOSTOP terminology flag, and I fiddled with it in the main thread, in the child thread, and in the environment that invokes Python, all to no avail. This is an educational process, but I'm not there yet.

, , Python ( SIGTTOU, , SIGTTOU), : PGRP , PID Python/PGRP.

'top' subprocess.check_output .Popen(), shell = True, shell = False std {out, err, in} , . 'top', '/bin/sh -c', , .

- , 'top' script, Python, os.fork() , ?

+5
3

, , , .

. SIGTTOU , Python forking , th = Thread(target=run) top, / , . , top ( ) , TTY.

man stty , :

 tostop (-tostop)
             Send (do not send) SIGTTOU for background output.  This causes back-
             ground jobs to stop if they attempt terminal output.

. script (stty -tostop; python my_script.py; stty tostop) ('-n') top.


: , - - tty, (, SIGTTIN/SIGTTOU).

Python script :

$SHELL #(controls TTY)
$ python my_script.py #(tcsetpgrp() is called to hand off control of TTY)
~~~ heck yeah, snake party ~~~
th = Thread(target=run) #(run target=proc in background)
print "Starting" #(still okay -- this gets handed up to the foreground interpreter)
th.start() 
#(here be dragons, std i/o in background fork)
subprocess.Popen(("/usr/bin/top", "-m", "io", "-d", "2", "10").communicate() 

FreeBSD , :

DESCRIPTION
       Top displays the top processes on the system and  periodically  updates
       this  information...

       Top makes a distinction between terminals that support  advanced  capa-
       bilities and those that do not...If the output of top is redi-
       rected to a file, it acts as if it were being run on a dumb terminal.

 ...
 OPTIONS
   -i     Use  "interactive" mode.  In this mode, any input is immediately
      read for processing.  See the section on "Interactive Mode"  for
      an  explanation of which keys perform what functions.  After the
      command is processed, the screen will  immediately  be  updated,
      even  if  the  command  was  not  understood.   This mode is the
      default when standard output is an intelligent terminal.
   ...
   -n     Use  "non-interactive" mode.  This is identical to "batch" mode.

top , ( Python), , , tty - , , , SIGTTIN, top STDIN SIGTTOU .

FreeBSD, , :

shell=True , 'top' PID , subprocess.Popen(..) , Python.

(n.b. : FreeBSD 8.1, .)

+2

SIGTTOU , :

, , - (. termios (3C)). SIGTTOU. SIGTTOU, SIGTTOU.

( )

? , top - , , , SIGTTOU - (, ).

, fork(), , . top , , , .

, , ps?


: http://www.technovelty.org/tips/sigttou-and-switching-to-canonical-mode.html , . , .

+1

Have you tried using the -b option with a vertex? It is designed for batch jobs and dumb terminals and can say that there is nothing to do from above, whatever it is, which causes a signal ...

0
source

All Articles