Determine what blocks a process on OSX using command line tools?

The name says it most. On Linux, this would be easy with strace and possibly lsof or /proc , and it was easy on OSX until truss was removed from OSX Leopard along with basic system calls (afaik).

The obvious approach is to solve this problem using dtrace , but, alas, as far as I understand, dtrace will not do it, because it catches events as they occur - and in my case the lock system call is already running, I would gladly agreed, if this can be solved using dtrace , by the way.

I saw that Xcode Instruments has a monitor that achieves something similar by taking periodic samples of the process stack (not sure which system calls it uses to do this!), Maybe something like this on the command line can be pretty good (so how it will display the stack right up to the library call, which ends the system call). To be useful for my use, this β€œfetch command-line tool” would have to find and parse the arguments found on the stack in order to be useful in determining which file descriptor we blocked.

Last: on Linux, you can usually do this as a regular user (in the absence of ptrace_scope tricks). It would be great if the OSX solution did not require root as well.

+4
source share
2 answers

You can use sample : sample PID -e

eg. for nc -l localhost 5999 you get a file with a graph of calls:

 Call graph: 9046 Thread_242504 DispatchQueue_1: com.apple.main-thread (serial) 9046 start (in libdyld.dylib) + 1 [0x7fff90a847e1] 9046 ??? (in nc) load address 0x102453000 + 0x166c [0x10245466c] 9046 __accept (in libsystem_kernel.dylib) + 10 [0x7fff94445996] 

And other useful information, such as downloaded binary images.

+5
source

I propose a solution that assumes the following:

  • the process can be signaled.
  • the process is single-threaded (the signal may not be processed in the blocking stream).
  • You have root access.

dtruss supports printing a full stack trace for each system call (-s argument).

Example:

terminal 1:

 $ python >>> import socket >>> s = socket.socket() >>> s.bind(('', 1234)) >>> s.listen(1) >>> s.accept() # blocking! 

terminal 2:

 $ dtruss -s -p `pgrep python` # or your python pid if you don't have pgrep (port install proctools) 

terimal 1:

 press Ctrl-C 

terminal 2:

 sigreturn(0x7FFF5FBFD660, 0x1E, 0x10031B3D0) = 0 Err#-2 libsystem_kernel.dylib`__accept+0xa # HERE IT IS! libpython2.7.dylib`PyEval_EvalFrameEx+0x42bf libpython2.7.dylib`fast_function+0xb3 ... 

the first frame on the stack if sigreturn (break code for signal handlers: http://linux.die.net/man/2/sigreturn ).

the second frame is the standard library wrapper for our system call: accept.

+2
source

Source: https://habr.com/ru/post/1442267/


All Articles