os.system vs os.system inside thread -> why is there any difference?

Discussion in 'Python' started by przemas_r@o2.pl, Nov 17, 2004.

  1. Guest

    Hello everybody.

    I've found python's behaviour I can't understand. Namely the way
    os.system () works depending if it's being run in Thread's run function
    or run in 'normal' way.

    >>> os.system ('arping -w 1 -c 1 -I eth1 192.168.0.2')

    ARPING 192.168.0.2 from 62.233.239.115 eth1
    Sent 1 probes (1 broadcast(s))
    Received 0 response(s)
    256
    >>>


    Here as you can see, arping command quits sending packets after 1 second
    and outputs failure (Received 0 response(s)) information.

    Now the same thing, but running from thread:

    >>> class A (threading.Thread):

    .... def __init__ (self):
    .... threading.Thread.__init__ (self)
    .... def run (self):
    .... os.system ('arping -w 1 -c 1 -I eth1 192.168.0.2')
    ....
    >>> A ().start ()
    >>> ARPING 192.168.0.2 from 62.233.239.115 eth1

    <lots of time and nothing happens>

    Now, although the only difference is that command arping is being run in
    thread, command never quits, informing about it's failure (-w 1 switch
    means that it should quit in 1 second). Mistery.

    Please help me if you know what's going on.

    --
    Przemys³aw Ró¿ycki
     
    , Nov 17, 2004
    #1
    1. Advertising

  2. Jeff Epler Guest

    Re: os.system vs os.system inside thread -> why is there anydifference?

    On POSIX systems, Python blocks the delivery of signals to threads, and
    installs a 'pthread_atfork' handler to restore the default behavior when
    fork() is called, because otherwise it leads to weird behavior in
    programs started with fork+exec.

    In the case of arping, I suspect the of the SIGALRM signal remains
    blocked, and arping waits forever for either the signal or the return
    packet.

    On Linux, at least, system() never calls the pthread_atfork
    handler, and the redhat maintainers have made it clear that they believe
    this behavior is allowed by the Open Group unix specification.

    Here's an entry-point into a python-dev thread on the subject:
    http://mail.python.org/pipermail/python-dev/2003-December/041311.html
    with links to the Open Group specification and the closed redhat bug.

    I suggest you write a replacement for system() in terms of fork + exec
    and then you should get the behavior you want.

    I continue to believe this is a redhat or glibc bug but my opinion
    doesn't seem to matter.

    Jeff

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.1 (GNU/Linux)

    iD8DBQFBm6T9Jd01MZaTXX0RAlAbAKCHMzLtJJ73ycAEkcumPFD0bhtlOgCdF/V8
    QD7ZNaLYeO0rId0JDZtFqik=
    =bdEp
    -----END PGP SIGNATURE-----
     
    Jeff Epler, Nov 17, 2004
    #2
    1. Advertising

  3. Guest

    Re: os.system vs os.system inside thread -> why is there any difference?

    Thanks for the answer.
    I've rewritten my code to use fork and exec calls instead of system
    call, but it still works only if run outside a thread. Here is the snippet:

    def ipState (self, ip):
    if os.fork () == 0:
    command = 'arping -f -w %s -c %s -I %s %s' % (self.wait,
    self.count, self.iface, ip)
    os.execvp ('arping', command.split ())
    os._exit ()
    else:
    status = os.wait () [1] & 0xff
    print status

    Changing start () to run () at the point where thread class is created
    and started (and thus running in main proccess instead) will cause the
    arping command to run properly. So the problem remains the same.

    Jeff Epler wrote:
    > On POSIX systems, Python blocks the delivery of signals to threads, and
    > installs a 'pthread_atfork' handler to restore the default behavior when
    > fork() is called, because otherwise it leads to weird behavior in
    > programs started with fork+exec.
    >
    > In the case of arping, I suspect the of the SIGALRM signal remains
    > blocked, and arping waits forever for either the signal or the return
    > packet.
    >
    > On Linux, at least, system() never calls the pthread_atfork
    > handler, and the redhat maintainers have made it clear that they believe
    > this behavior is allowed by the Open Group unix specification.
    >
    > Here's an entry-point into a python-dev thread on the subject:
    > http://mail.python.org/pipermail/python-dev/2003-December/041311.html
    > with links to the Open Group specification and the closed redhat bug.
    >
    > I suggest you write a replacement for system() in terms of fork + exec
    > and then you should get the behavior you want.
    >
    > I continue to believe this is a redhat or glibc bug but my opinion
    > doesn't seem to matter.
    >
    > Jeff
     
    , Nov 17, 2004
    #3
  4. Jeff Epler Guest

    Re: os.system vs os.system inside thread -> why is there anydifference?

    On Thu, Nov 18, 2004 at 12:00:06AM +0100, wrote:
    > Thanks for the answer.


    You're welcome. I'm sorry it didn't work out.

    I wrote a pair of standalone programs (no need for arping) to check this
    behavior. The bad news is that my program failed on 2.2.2 and 2.3.2.
    It only succeed on a CVS version of Python 2.4b2.

    To run the test, "python prz.py". It should print "0" twice, because
    each time "alarmed.py" should exit from within the SIGALRM signal
    handler. On 2.2 and 2.3, it prints "0" (works in the main thread) then
    "1" (doesn't work in another thread)

    Jeff

    Subprogram "alarmed.py":
    #------------------------------------------------------------------------
    #!/usr/bin/python
    import signal, time, sys, os
    signal.signal(signal.SIGALRM, lambda *args: sys.exit(0))
    os.kill(os.getpid(), signal.SIGALRM)
    sys.exit(1)
    #------------------------------------------------------------------------

    Main program "prz.py":
    #------------------------------------------------------------------------
    import threading
    import os
    import signal

    def system(s):
    p = os.fork()
    if p == 0:
    os.execvp("/bin/sh", ['sh', '-c', s])
    os._exit(99)
    else:
    p, status = os.waitpid(p, 0);
    return os.WEXITSTATUS(status)

    class T(threading.Thread):
    def run(self):
    print system("python alarmed.py")

    t = T()
    t.run()

    t = T()
    t.start()
    t.join()
    #------------------------------------------------------------------------

    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v1.2.1 (GNU/Linux)

    iD8DBQFBnLGnJd01MZaTXX0RAiORAJ9EYMNVONRtRNy2Tw0UiggOw/hUiQCgkzz8
    qZwK8VJTpTrPgTGN5Ru0Qok=
    =DRf1
    -----END PGP SIGNATURE-----
     
    Jeff Epler, Nov 18, 2004
    #4
  5. Guest

    Re: os.system vs os.system inside thread -> why is there any difference?

    I've tested the code you sent. Obviously the result was the one, you
    reffered to as python 2.2.2 or 2.3.2 specific.
    Ok, so it's high time I switched to new 2.4.x release.

    Thanks again for clarifying me this issue.


    Jeff Epler wrote:
    > On Thu, Nov 18, 2004 at 12:00:06AM +0100, wrote:
    >
    >>Thanks for the answer.

    >
    >
    > You're welcome. I'm sorry it didn't work out.
    >
    > I wrote a pair of standalone programs (no need for arping) to check this
    > behavior. The bad news is that my program failed on 2.2.2 and 2.3.2.
    > It only succeed on a CVS version of Python 2.4b2.
    >
    > To run the test, "python prz.py". It should print "0" twice, because
    > each time "alarmed.py" should exit from within the SIGALRM signal
    > handler. On 2.2 and 2.3, it prints "0" (works in the main thread) then
    > "1" (doesn't work in another thread)
    >
    > Jeff
    >
    > Subprogram "alarmed.py":
    > #------------------------------------------------------------------------
    > #!/usr/bin/python
    > import signal, time, sys, os
    > signal.signal(signal.SIGALRM, lambda *args: sys.exit(0))
    > os.kill(os.getpid(), signal.SIGALRM)
    > sys.exit(1)
    > #------------------------------------------------------------------------
    >
    > Main program "prz.py":
    > #------------------------------------------------------------------------
    > import threading
    > import os
    > import signal
    >
    > def system(s):
    > p = os.fork()
    > if p == 0:
    > os.execvp("/bin/sh", ['sh', '-c', s])
    > os._exit(99)
    > else:
    > p, status = os.waitpid(p, 0);
    > return os.WEXITSTATUS(status)
    >
    > class T(threading.Thread):
    > def run(self):
    > print system("python alarmed.py")
    >
    > t = T()
    > t.run()
    >
    > t = T()
    > t.start()
    > t.join()
    > #------------------------------------------------------------------------
     
    , Nov 18, 2004
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Gonzalo Moreno
    Replies:
    2
    Views:
    12,436
  2. kyo
    Replies:
    0
    Views:
    327
  3. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    909
    Mark Rae
    Dec 21, 2006
  4. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,995
    Smokey Grindel
    Dec 2, 2006
  5. Replies:
    5
    Views:
    2,267
    Dominick Baier [DevelopMentor]
    Nov 8, 2005
Loading...

Share This Page