Errno::EMFILE - "Too many open files # rb_sysopen" when opening first file - ruby

I have an application that's using ruby 2.2.3 . For most users the application is working fine but for 2 users they are running into the error "Too many open files # rb_sysopen - C:\Users\Samuel\AppData\Roaming\Oneshot\save.dat (Errno::EMFILE)"
This is happening on the first file that the game tries to write to from the ruby level. I've had the affected users run process explorer to check how many file handles the program has open but it only has 30 open at most, so I don't think they actually have too many open files. The directory exists on the user's computer so it's not an issue with that either. Does anyone have any ideas what else could be causing this error to be thrown?
This is the ruby code that's causing the issue, I don't think anything is wrong with it (it's breaking right when it opens, not during the dump):
def save
if ($game_variables[3] == 0) #don't save if intro variable isn't set
return
end
File.open(SAVE_FILE_NAME, 'wb') do |file|
# Wrire frame count for measuring play time
Marshal.dump(Graphics.frame_count, file)
# Increase save count by 1
$game_system.save_count += 1
# Save magic number
# (A random value will be written each time saving with editor)
$game_system.magic_number = $data_system.magic_number
# Write each type of game object
Marshal.dump($game_system, file)
Marshal.dump($game_switches, file)
Marshal.dump($game_variables, file)
Marshal.dump($game_self_switches, file)
Marshal.dump($game_screen, file)
Marshal.dump($game_actors, file)
Marshal.dump($game_party, file)
Marshal.dump($game_map, file)
Marshal.dump($game_player, file)
Marshal.dump($game_followers, file)
Marshal.dump($game_oneshot, file)
Marshal.dump($game_fasttravel, file)
Marshal.dump($game_temp.footstep_sfx , file)
end
save_perma_flags
end

Related

"Too many open files" error when using named pipes

I'm running 2 scripts and after a while, I'm getting Too many open files # error/blob.c/ImageToFile/1832.
Simplified version of the first scripts. It's supposed to read images written to image_pipe, process them, and write them to ocr_pipe for the OCR to read.
# creates 2 named pipes
File.mkfifo(image_pipe) rescue nil
File.mkfifo(ocr_pipe) rescue nil
while image = Image.read(image_pipe)
# do some stuff with `image`...
end
The second script is using ffmpeg to extract frames from a video, writing them to image_pipe
# image_pipe is the same as the script above.
(14..movie.duration).step(0.5) do
`/usr/local/bin/ffmpeg [some options...] #{image_pipe}`
end
I think the issue is RMagick opening too many file descriptors when reading the images in the loop of the first script, but I'm not sure how to stop that from happening. The Magick::Image class doesn't have a close method or anything, afaik.
I did not find the root cause of the issue, but ulferts helped me find a workaround that's acceptable for me.
Instead of letting RMagick open the file itself, we should handle it on our side, and then use .from_blob to create the Magick::Image instance.
while f = File.read(image_pipe)
image = Image.from_blob(f)
# ... do stuff with image.
end

Opening a Text File in Ruby

I am trying to create a program that will count the word frequency within a text file that I have created. I have a text file titled moms_letter.txt and this is my code:
word_count = {}
File.open("moms_letter.txt", "r") do |f|
f.each_line do |line|
words = line.split(' ').each do |word|
word_count[word] += 1 if word_count.has_key? word
word_count[word] = 1 if not word_count.has_key? word
end
end
end
puts word_count
The problem I am getting is when I go to run the file, I get the error:
there is no such file or directory - moms_letter.txt (Errno: : ENOENT)
Not quite sure why this is occurring when I have the text file created.
Any help is appreciated.
I am also newbie in Ruby, so thanks for the patience.
You must be executing your program from outside the directory where your moms_letter.txt file resides. You need to use an absolute path to open your file. Or, execute your program always from the directory where the .txt is. So, instead of using "moms_letter.txt" go with "complete/path/to/file/moms_letter.txt".
I'm fairly new to Ruby too, but have worked with text files a bit recently. It may seem like an obvious question, but is the text file you're trying to open in the same directory as your .rb file? Otherwise you'll need to include the relative path to it.
For troubleshooting sake, try File.new("temp.txt", "w") and then File.open("temp.txt", "r") to see if that works. Then you'll know if it's an issue with your code or with the txt file you're trying to access.
Also using File.exists?("moms_letter.txt") will help you determine whether you can access that file from within your .rb script.
Hope that helps!

My gem cannot see a dictionary text file, I cannot get the path

I wrote an implementation of the hangman game. (It is played on the terminal). The game is working fine but I usually have some problems getting my program to open a dictionary txt file from where the word will be generated. Below is my code for generating the word
def word_generator(min, max)
words = File.open("../dictionary.txt"), "r").readlines.map!(&:chomp)
level_words = words.select { |i| i.length >= min && i.length <= max }
random_index = rand(level_words.length)
#game_word = level_words[random_index]
end
This approach works fine when I play my game locally and the dictionary text file is just one directory level away from my ruby file. Here is the problem:
When I package the project as a gem, and install it. It will throw this error in initialize': No such file or directory # rb_sysopen /Users/andeladev/Desktop/paitin_hangman/bin/dictionary.txt (Errno::ENOENT). It will only run fine when I put the text file in the present working directory of the terminal.
How do I go about writing the path in the argument passed to File.open that will tell the program to look for the file in the gem path rather than the present working directory.
Try this:
file_name = File.join(File.dirname(File.expand_path(__FILE__)), '../dictionary.txt')
words = File.open(file_name, "r").readlines.map!(&:chomp)

how to reload external file every time?

I have a ruby script where my "config" is in an extra file. It's called ftp_config.rb. Then I have filetrack.rb that downloads files from a ftp server - what files/directories is specified in ftp_config.rb. And finally I got rufus_download.rb that is calling a function from filetrack.rb every day so I get all new files from the server.
Everything works fine just I want to know how to make it so when I edit ftp_config.rb the changes are picked up by the script without the need to restart rufus_download.rb.
currenly
rufus_download.rb contains require_relative 'filetrack'
filetrack.rb contains require_relative 'ftp_config'
Right now if I add new files to be downloaded to ftp_config.rb I need to restart rufus
require_relative returns false if the file you have requested is already loaded to your ruby script and returns true if you haven't
If you want changes to be loaded directly you need to load files
load 'path/to/ftp_config'
every time your script executes it will load / reload the script
EDIT:
you can load by expanding path of the current ruby script:
load ::File.expand_path('../ftp_config.rb', __FILE__)
Assuming that files are in the same folder
EDITEND
hope that helps
You need a gem that monitors filechanges like "sinatra/reloader" for Sinatra and eg filewatcher or listen for desktop apps. After detecting an update you load the script, not require, that only loads a script once.
Here an example of filewatcher.
STDOUT.sync = true
FileWatcher.new(['c:/test/scans']).watch() do |filename, event|
puts filename
if(event == :changed)
puts "File updated: " + filename
end
if(event == :delete)
puts "File deleted: " + filename
end
if(event == :new)
puts "Added file: " + filename
end
end

ruby 2.2 , how to display the current content of the file?

in a ruby 2.2. script, I am writing an xml file
#filehandle << '<plist version="1.0">'
...
#filehandle << "\n<#{element_name}>"
..
during debugging , I would like to display the current content, how can I get it as it's not yet closed, but only cached ... ?
thanks for your suggestions
byebug
#filehandle.class
File
#filehandle
#<File:./AlbumData-new.xml>
You can execute these calls in order to display the content (I assume that the file is opened for reading and writing, i.e., mode is r+, w+ or a+)
#filehandle.flush # Make sure everything is written to disk
#filehandle.seek(0) # So we can read from the beginning
#filehandle.read # Read everything

Resources