Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zombie processes after reader.close() #164

Open
svleeuwen opened this issue Apr 28, 2015 · 24 comments
Open

Zombie processes after reader.close() #164

svleeuwen opened this issue Apr 28, 2015 · 24 comments
Labels
bug Issues that report (apparent) bugs. performance Speed/performance of code or individual functionality.

Comments

@svleeuwen
Copy link

Hi,

When MoviePy finishes rendering I'm still left with a lot of zombie ffmpeg processes. (http://cl.ly/image/1X2h0o0J103K)

These don't use any resources, but there is a maximum nr of processes ofcourse.
Is this bad? Can this be overcome?

@Zulko
Copy link
Owner

Zulko commented Apr 28, 2015

What do you mean by "after rendering" ? Even after the python session is closed ?

If you still have VideoFileClips around it is normal that their processes are still there. Do you destroy the VideoFileClips ?

One thing I generally do is encapsulate the whole rendering process inside a function. This way all the clips are destroyed when we leave the function and there are no preocesses left.

Tell me if this didn't answer your question.

@svleeuwen
Copy link
Author

My MoviePy code is executed by a Celery task send from a Django view. So as long as the parent process lives (in this case Celery) the ffmpeg processes will stay alive. (without using resources though)

I explicitly call clip.reader.close() because somehow a reference to the ffmpeg_reader still exists when I just do del clip. (where clip is a VideoFileClip instance)

@svleeuwen
Copy link
Author

I see that they get reused when compiling another video. So it's actually not so bad.

@Zulko
Copy link
Owner

Zulko commented Apr 28, 2015

That's strange. Are you reusing some clips in common in your different requests ?

@alesgenova
Copy link

svleeuwen,
did you ever get to fix it?
I'm also using moviepy in combination with django and celery, and ffmpeg processes get left behing
I've tried many combinations of clip.close(), del clip, del clip.audio and so on, but I don't seem to be able to solve it once and for all.
Specifically the ffmpeg processes that seem to get left behind the most are ones for reading the audio from the input VideoFileClip.
Any help is appreciated

@svleeuwen
Copy link
Author

svleeuwen commented Jan 2, 2017

@alesgenova: I was under pressure to finish the project so I just watched the processes and killed them if they stayed around for too long.

But did you try @mbeacom's fix above?

@alesgenova
Copy link

Yes, I gave that a shot, but it didn't solve it completely, it was still unreliable.
If anyone is interested, I ended up having all my moviepy/celery tasks in a separate queue whose worker is set to have --max-tasks-per-child=1, so that the worker is started fresh after each task.
It's probably not an elegant solution, but at least it insures memory doesn't leak and I don't leave processes behind. And above all, it doesn't require a manual input from me!

@svleeuwen
Copy link
Author

Ah, now I remember. I also used --max-tasks-per-child=1 😄

@mbeacom
Copy link
Collaborator

mbeacom commented Jan 3, 2017

@alesgenova It's odd that you're still experiencing zombie/defunct ffmpeg processes with my referenced fork. Did you uninstall/manually install the fork egg? pip uninstall moviepy -y; pip install -e git+git://github.com/mbeacom/moviepy.git@fix-ffmpeg-zombies#egg=moviepy. All reading jobs in my test scenarios no longer result in zombie processes.
Hope it helps!

@mbeacom mbeacom added the bug Issues that report (apparent) bugs. label Jan 30, 2017
mbeacom pushed a commit that referenced this issue Jan 30, 2017
Fix #164 - Resolve ffmpeg zombie processes
@mbeacom
Copy link
Collaborator

mbeacom commented Jan 30, 2017

@svleeuwen @alesgenova Please pull an update from master directly and let me know if you're still experiencing this issue. Hopefully we'll be able to merge the update to PyPi soon.

@whelly
Copy link

whelly commented Mar 13, 2017

I'm still experiencing this issue, even with trying all the solutions in this thread. I'm using the master branch currently, Python 2.7, and Windows 10. Any other ideas to force close the FFMPEG processes? My end goal is to delete some of the source video files after the render is complete, but I'm getting Error 32 since FFMPEG still has control of those files. Using reader.close() on the various clips does exit out some of the FFMPEG processes but I can't get all of them for some reason. If there is the audio clip equivalent of reader.close() maybe that would solve the issue.

Edit: Also, even though I'm able to use close() for video clips and close_proc() for audio, there's still one FFMPEG process left. I have no idea where it comes from or how to close it manually.

@Mordokkai
Copy link

Mordokkai commented Apr 27, 2017

Hi,
I had also an issue like that. Since I was running my program on thousands of videos, I got my RAM rapidly full. I've just looked at the moviepy code and it seems that the destructor of VideoFileClip is never called when I use "del clip". It's seems to be related to the fact that "del" doesn't call "del()" in every case (cf http://stackoverflow.com/questions/41516287/python-del-does-not-work-as-destructor/41516416).
So I explicitly used clip.__del__() every time. I did the same in AudioFileClip, adding self.reader.__del__() in the destructor and idem in VideoFileClip i added self.audio.__del__() and self.reader.__del__() in the destructor. It's very ugly but it seems to work for me.

@whelly
Copy link

whelly commented Apr 27, 2017

Thanks @Mordokkai, I did something a little different because del() didn't seem to work for me. I figured out recently that the audio portion of the clip also has a reader you can close, but the function is named differently from the video reader. Call both these on the clip you need to take control of: clip1.reader.close() and clip1.audio.reader.close_proc().

@Mordokkai
Copy link

Yes, sorry, soon after I sent my answer, I realized that my solution raised other issues (about missing attributes). I tried to fix it but I didn't succeed. I finally used subprocess.call(["pkill -9 -f " + video_name[2:]],shell=True) but it's a very ugly code. I'll try your solution. Thanks a lot :)

@ghost
Copy link

ghost commented Apr 28, 2017

This is a note to the developers of moviepy (which also includes myself))..

We probably need to modify the close_proc function so that it matches the video reader class and rename the function to close.

@kstohr
Copy link

kstohr commented Nov 3, 2017

Hey there... just wanted to check in and see if this issue is being worked on... I am not an expert in processes.. but getting zombie processes running a subprocess to split audio from a movie file.

@Mordokkai
Copy link

I use this function to close my video clips and it works for me. There is probably a better solution, and maybe this issue was fixed since april.

def close_clip(clip):
        try:
                clip.reader.close()
                del clip.reader
                if clip.audio != None:
                        clip.audio.reader.close_proc()
                        del clip.audio
                del clip
        except Exception as e:
                sys.exc_clear()

@nathanielws93
Copy link

I'm still running into this issue.- I'm trying to render about 100 videos (each one consists of several VideoFileClip subclips), but each time I render 5 videos or so, I get the "Handle is Invalid" error. I've had to restart & clear my Jupyter kernel after every 4-5 videos I make.
I tried using Mordokkai's script, but I'm still getting the error. Any tips?

@cesarandreslopez
Copy link

@Mordokkai 's solution worked for me. I just call that function after every clip is used.

vishruth pushed a commit to vishruth/VideoAnnotations that referenced this issue Jul 22, 2018
Readers were being left behind on Windows only.

Known issue with MoviePy:
Zulko/moviepy#164
@raj6996
Copy link

raj6996 commented Nov 4, 2018

Today I got error:

C:\Users\YL>python "F:\Python36\videogrep1.py" --input "D:\I.mp4" --search "Rule"
D:\I.srt
[+] Searching for video file corresponding to 'D:\I.srt'.
[+] Found 'D:\I.mp4'.
[+] Search term 'Rule' was found in 1 places.
[+] Creating clips.
125.25 to 128.836: Rule number one, never take your eye off your opponent.
[+] Concatenating clips.
[+] Writing ouput file.
[MoviePy] >>>> Building video supercut.mp4
[MoviePy] Writing audio in temp-audio.m4a
100%|█████████████████████████████████████████████████████████████████████████████████| 80/80 [00:00<00:00, 170.67it/s]
[MoviePy] Done.
[MoviePy] Writing video supercut.mp4
100%|███████████████████████████████████████████████████████████████████████████████| 108/108 [00:00<00:00, 216.00it/s]
[MoviePy] Done.
[MoviePy] >>>> Video ready: supercut.mp4

Exception ignored in: <bound method FFMPEG_AudioReader.del of <moviepy.audio.io.readers.FFMPEG_AudioReader object at 0x00000245288DB5C0>>
Traceback (most recent call last):
File "F:\Python36\lib\site-packages\moviepy\audio\io\readers.py", line 251, in del
self.close_proc()
File "F:\Python36\lib\site-packages\moviepy\audio\io\readers.py", line 147, in close_proc
self.proc.terminate()
File "F:\Python36\lib\subprocess.py", line 1139, in terminate
_winapi.TerminateProcess(self._handle, 1)
OSError: [WinError 6] The handle is invalid

@GE3999
Copy link

GE3999 commented Dec 6, 2018

Thanks
I solved this problem
add clip.close() after write_gif()

@jaykm
Copy link

jaykm commented Sep 18, 2019

I am still having this issue, is there any known fix? I am closing every single clip/video in my program.

@ajiteshsingh
Copy link

Yes, sorry, soon after I sent my answer, I realized that my solution raised other issues (about missing attributes). I tried to fix it but I didn't succeed. I finally used subprocess.call(["pkill -9 -f " + video_name[2:]],shell=True) but it's a very ugly code. I'll try your solution. Thanks a lot :)

I was about to remove moviepy as a dependency then saw your solution and it worked. Thanks buddy

@keikoro keikoro added the performance Speed/performance of code or individual functionality. label Jan 14, 2022
@ghost
Copy link

ghost commented Jan 17, 2023

If anyone is still having this issue now (especially with any Audio/VideoFileClip) when trying to delete any tmp files, please try this function. tmp_dir is the path with all your files you wish to delete, and the audio_file_clip is any Audio/VideoFileClip object that is holding you back in life.

def zombie_killer(tmp_dir, audio_file_clip) -> None:
        os.chdir(os.path.dirname(os.path.abspath(__file__)))
        for real_file in os.listdir(tmp_dir):
            try:
                os.unlink(os.path.join(tmp_dir, real_file))
            except PermissionError:
                try:
                    file_name = os.path.join(tmp_dir, real_file)
                    for proc in psutil.process_iter():
                        try:
                            files = proc.open_files()
                            for tmp_file in files:
                                if tmp_file.path == file_name:
                                    if sys.platform == "win32":
                                        subprocess.call(['taskkill', '/F', '/PID', str(proc.pid)])
                                    else:
                                        os.kill(proc.pid, signal.SIGTERM)
                        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                            pass
                    audio_file_clip.close()
                    os.unlink(os.path.join(tmp_dir, real_file))
                except Exception as e:
                    print(e)
                    pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issues that report (apparent) bugs. performance Speed/performance of code or individual functionality.
Projects
None yet
Development

No branches or pull requests