1

The application in question is DaVinci Resolve. I start it from terminal. And when I close it, the message "Socket Disconnected" from the app is written to the terminal output. Then the bash prompt appears as normal. I start typing the new command, and suddenly another message appears in terminal "Socket Disconnected". And this interferes with the input I made. It looks like this:

[andrew@unihost ~]$ davinci-resolve
... # Now I exit the application.
Host 'Fusion' Removed
FusionScript Server [37457] Terminated
Socket disconnected
[andrew@unihost ~]$ ls ls Socket disconnected
wtf!!!^C
[andrew@unihost ~]$

Video demo: https://youtu.be/arcCOjrN7kw

Why this is happening and is there a way to prevent this?

My guess is that there is subprocess of the main process, which still is alive even after main process dies. I have found this answer. Is that the developer's fault? Can I workaround this somehow (maybe nohup for child process)?

Ashark
  • 909
  • "Can I workaround this somehow (maybe nohup for child process)" - have you tried the obvious nohup davinci-resolve? – Chris Davies Apr 05 '22 at 19:13
  • Thanks for suggestion. I tried, but it completely removes everything from the terminal. The idea of running with terminal is to be able to see messages. Otherwise, it is no much different from launching with desktop file. – Ashark Apr 05 '22 at 19:25
  • Well, yes, of course it removes all the text from the terminal. It shouldn't stop the interface running, though – Chris Davies Apr 05 '22 at 19:28

4 Answers4

1

Preliminary note

I haven't tested davinci-resolve at all. This answer is designed to be generic.


Analysis

Your shell waits for davinci-resolve to exit before it puts itself back in the foreground and prints the prompt. Apparently some child (or further descendant) of the main davinci-resolve prints the unwanted message after the main process exits and the shell reacts.


Solution

A solution may be as easy as:

davinci-resolve | cat

The trick is cat won't exit until all processes writing to the pipe close their end of the pipe. The troublesome child probably inherits the stdout from the main davinci-resolve, so cat will wait for it. Normally this will work even if the unwanted message is printed to stderr or /dev/tty (i.e. it bypasses our cat). What matters is the child keeps the pipe open, even if it's printing to elsewhere.

There are disadvantages:

  • The exit status of the entire pipe will come from cat, not from davinci-resolve. In some shells you can do something about it.

  • stdout and stderr from davinci-resolve (and its descendants) will lose sync because the former goes via cat and the latter doesn't.

  • If you Ctrl+c then you will kill the cat, possibly before the other processes finish printing, so you may miss some output you do want to see. Additionally if the troublesome message gets printed to stderr then it will be printed anyway, possibly after you see the prompt.

    You can make the cat immune to Ctrl+c though:

    davinci-resolve | sh -c 'trap "" INT; exec cat'
    
  • The troublesome process may close or redirect its stdout early and still print to stderr. In this case cat will not wait for it.

  • The troublesome process may be designed to remain and the unwanted message does not mean the process exits. If the process remains and keeps the pipe open then our cat will remain; you obviously don't want this. It seems unlikely any descendant of davinci-resolve remains (unless there's a bug), but in general it may happen.

For some of these reasons you may want to pass stdout and stderr via cat. Making the cat immune to Ctrl+c is still a good idea:

  davinci-resolve 2>&1 | sh -c 'trap "" INT; exec cat'

Note now you cannot tell apart stderr of davinci-resolve (and its descendants) from stdout, they both go via cat and its stdout. It shouldn't be a problem, as you wanted them to mix in the terminal anyway. If you ever want to redirect or capture them separately then you should drop our contraption and start from scratch.

It may be the troublesome process closes or redirects its stdout and stderr early, and it prints the unwanted message directly to /dev/tty (example). In this case our cat cannot help.


Shell function

You can implement our solution as a shell function:

davinci-resolve() {
   command davinci-resolve "$@" 2>&1 | sh -c 'trap "" INT; exec cat'
}

The function supports passing arguments to davinci-resolve, but its exit status comes from cat, not from davinci-resolve process (if it's a problem then see the already given link for ideas).

  • 1
    Thanks for the extensive generic answer. davinci-resolve | cat did the trick for me. As this davinci-resolve is itself my wrapper script over a /opt/resolve/bin/resolve binary, I will add that | cat inside it. – Ashark Apr 06 '22 at 09:12
  • @Ashark I concur. In case of a custom wrapper this is a reasonable approach. – Kamil Maciorowski Apr 06 '22 at 09:19
  • Is it possible to run arbitrary command when you ctrl +c? I want to run kill -9 $(pidof -s resolve) there. I tried /opt/resolve/bin/resolve | sh -c 'trap "echo bye" INT; exec cat' there, but when I do ctrl + c, just "^C" appears, and echo does not print anything. – Ashark Apr 17 '23 at 03:26
  • 1
    @Ashark It's a substantially different question. Posting it as a comment under a 1-year-old answer is a poor strategy. Ask a new question please (after doing research and making sure it's not a duplicate of some existing one). Include a link to the above question if you think it provides context. – Kamil Maciorowski Apr 17 '23 at 03:47
0

The background process is not actually interfering with your shell, it's just scribbling on your screen and the output from the background process and the shell are mixing.

There are several approaches to fix this:

  • You can use something like nohup or file redirection to remove the messages from your terminal, possibly saving them to a file.
  • You can ignore the mess and just keep typing, or if you haven't typed anything, just hit return to get a fresh prompt.
  • You can read the messages sent by the background process and then use a command line editing keystroke to refresh what you typed and make it readable again. In a plain cooked terminal mode, Ctrl-R will do this. In many other applications like bash, Ctrl-L will clear the screen and reprint the prompt and what you typed.
  • You could run that application in a dedicated window and use the power of a graphical windowing system to open another window that is not polluted with its output. :) (I keep a small window off to the side just to run such noisy applications.)
  • If this is occurring after you have ended the application, and it has left worker threads behind that you want to discontinue, you may be able to find them with ps -t (to show what is running on the current terminal) and kill them.
user10489
  • 6,740
  • Ignoring the problem and continue typing or clearing the terminal is obvious. But it is not actually a workaround. The pollution is not so high, just that string. But it is a bit annoying. Every time I end the application, I wait these several seconds for this "Socket disconnected" message before continuing. So, as not being able to change the application (the application is proprietary), I cannot fix that, meaning only the main process can detach the child from terminal? About redirection, is it possible to redirect to file, and then print (continuously) that file back to terminal? – Ashark Apr 06 '22 at 02:11
  • You could redirect to a file and then use tail -f to watch what is added to teh file. But I don't see how this helps, as you'd still have the same problem, although with tail I suppose you could at least start / stop / restart it. But you'd also have a file that grows which could be its own problem. – user10489 Apr 06 '22 at 08:49
0

You can type control-l to clear the screen. This will clear the "Socket disconnected" messages but will keep your command prompt and partially written command intact. Unfortunately it will also clear the output of davinci-resolve, which may or may not be okay for what you're trying to do.

sarac
  • 1
0

If the "Socket disconnected" messages come pretty quickly after the main process exits, you could add ; sleep 2 to your command and put it in a shell alias. It would basically be a way to remind yourself not to type a new command right away. To do this, add

alias davinci-resolve="davinci-resolve; sleep 2"

to your .bashrc

sarac
  • 1
  • 3
    In most shells an alias replaces text with text, there is no logic in it. If davinci-resolve can take arguments and one ever wants go give argument(s) then your alias will misbehave, because the argument(s) will appear after sleep 2. A function like davinci-resolve() { command davinci-resolve "$@"; sleep 2; } is better. (Note if there is the alias already then it will interfere when you define the function this way; you need to unalias davinci-resolve first.) – Kamil Maciorowski Apr 06 '22 at 05:45