How to get data to a running ruby process? - ruby

I have a datastore with a cache and a db, simple. The tricksy part is that I want a way to control if the the datastore hits the db in a real-time way. That is to say while the process is running I want to be able to toggle if it's connected to the db or not.
I looked into env variables, but it doesn't seem like those get updated as the process runs. Is there a simple way to get a bit from the command line into the running process, or do I just need to rely on ops being able to drop the db listeners in case of disaster?
Note that this is all being done in vanilla ruby - not ruby on rails.
Thanks!
-Jess

I think you can use named pipes for simple communication:
#pipes.rb:
f = File.open 'mypipe', 'r+'
loop do
begin
s = f.read_nonblock 1
rescue Exception
end
case s
when '0'
puts 'Turn off DB access!'
when '1'
puts 'Turn on DB access!'
end
sleep 1
end
And you can control your db access externally by writing to the named pipe:
jablan-mbp:dev $ echo 101 > mypipe
Which results in:
jablan-mbp:dev $ ruby pipes.rb
Turn on DB access!
Turn off DB access!
Turn on DB access!

A shared-memory strategy might be worth considering. Assuming you're running on a POSIX system, check out mmap for memory-mapped files, and SysVIPC for message queues, semaphores, and shared memory.

Assuming *NIX, have you considered signals? (kill -HUP pid) - http://ruby-doc.org/core/classes/Signal.html

Related

What's the meaning of `0x0100` for a `Process::Status` value?

I have code:
Process.spawn(RbConfig.ruby, "a ruby file", "arg")
and I wait and check its status by:
Process.wait
$?.success?
Most of the time, it works well. But sometimes, $?.success? is false and $?.to_i is 0x0100. It seems the failed process didn't get a chance to run any code before 0x0100 was returned (I didn't send any signal to the process). I wonder the meaning of 0x0100. I further want to know if Ruby's spawn may fail when the command is all right. Could anyone help?
Here is a quote from the Process::Status class documentation:
Posix systems record information on processes using a 16-bit integer. The lower bits record the process status (stopped, exited, signaled) and the upper bits possibly contain additional information (for example the program's return code in the case of exited processes). Pre Ruby 1.8, these bits were exposed directly to the Ruby program. Ruby now encapsulates these in a Process::Status object. To maximize compatibility, however, these objects retain a bit-oriented interface. In the descriptions that follow, when we talk about the integer value of stat, we're referring to this 16 bit value.
The method Process::Status#to_i returns this stat as a Fixnum.
OK, finally I got the answer: when a ruby process throws an uncaught exception, the process' exit code will be 0x0100. This is from my observation on Ubuntu 14.04 and Ruby 2.2. For example: there's ruby file a.rb, and in another file, say src.rb, there's a code snippet:
Process.spawn(RbConfig.ruby, "a.rb", "arg")
Process.wait
If a.rb throws an uncaught exception, then $?.to_i will be 0x0100. What's more, I also observed that a.rb sometimes didn't get executed before its process failed with 0x0100. So I guess it may have something to do with the Ruby interpreter since I'm sure a.rb is OK.
Anyway, there' no official document mentioning the exact behavior. So my experience is for your reference.

Detecting when a subprocess expects input in Ruby

I have a console application (command response type) that I want to control its IO so I can feed it with a script from file and then continue the execution manually when the script execution is finished.
my script is this:
ARGF.readlines = commands
IO.popen('ConsoleApplication') { |io|
begin
puts io.gets
sleep 0.1
end while ????
}
As I observed IO.popen connects the input of io object to the process IO but the output should be read. If by some means the output was displayed automatically or I could detect when the process is waiting for input where ???? is I think I could consider this matter as done!
My further workaround results:
Expect do not work on widows because windows do not support pseudo terminals(PTY) so I can't use ruby_expect like libraries for windows!
I tried IO.select in combination with IO.read_nonblock which encounters "bad file pointer". Some people said that non-blocking IO is not supported in windows as well
So I used some special strings to synchronize the read-write sequences myself and the task is done.

Non-blocking readline for STDIN?

I can't figure out why IO methods won't work on STDIN, when properly set to non-blocking mode:
require 'fcntl'
stdin_flags = STDIN.fcntl(Fcntl::F_GETFL)
p stdin_flags #32770
p STDIN.fcntl(Fcntl::F_SETFL, stdin_flags | Fcntl::O_NONBLOCK) # 0
p STDIN.fcntl(Fcntl::F_GETFL) # 34818
#at_exit { STDIN.fcntl(Fcntl::F_SETFL, stdin_flags & ~Fcntl::O_NONBLOCK) }
STDIN.readline # this call blocks, IO::EAGAINWaitReadable expected
exit
IO.fcntl successfully sets non-blocking mode but all IO functions like read, readline, gets, readchar ignore the mode and hang at reading when no input has been received.
Setting sync mode to true has no effect.
If I replace STDIN.readline with the shell call system('read line') it does work correctly. It won't wait or would wait for input depending if non-blocking mode was set.
I'm aware of IO.read_nonblock but looking for an efficient way how to read newline terminated strings. Calling read_nonblock for each single character is painfully slow.
Can anybody explain this (mis)behavior?
It's a bit unfortunate but standard functions from IO module seem to not respect status flags associated with a file descriptor.
One of the working solutions is use of IO.select class method for input polling, then read the data with regular methods as they become available.
Be aware when line processing methods are used, code may hang until terminating newline character gets consumed. It's advisable to enclose polling code in Timeout block when things are going out of control.
In cases when amount of characters/bytes is known beforehand, stock IO.read_nonblock would simply serve well.

how to kill orphaned winword.exe in matlab

Running matlab R2010B on Windows 7 Enterprise
In matlab scripts, I save a bunch of results to a word file and then at the end, close and quit word. The code I use is:
WordFname = ['BatInfoDoc' sprintf('%0.3f',now) '.doc']; % serialnumbered filenames
WordFile = fullfile(pwd,WordFname);
WordApp = actxserver('Word.Application');
WordDoc = WordApp.Documents.Add;
WordDoc.SaveAs2(WordFile);
....
WordApp.Selection.TypeText([title2 title3 title4 title5 title6]);
WordApp.Selection.TypeParagraph;
then finally at the end of the script
WordDoc.Close;
WordApp.Quit;
The problem I have is that through my development process, I often crash the matlab script and wind up leaving orphaned WINWORD.EXE processes, each one of which keeps a lock on the file it had been writing.
Up until now I have been using TaskManager to kill these processes one at a time by hand. Having been developing all morning, I find myself with around 20 files I can't delete because they are locked by about 11 orphaned WINWORD.EXE processes!
My question(s):
1) Is there an elegant way to handle the file writing and saving and closing and so on so I don't lock up files and processes when my script crashes out before I get to the part where I close the file and quit word?
2) Is there an elegant way to determine the bad processes from within matlab script and go through and delete them from within a matlab script? That is, can I code my matlab so it cleans up after itself?
ADDED A FEW MINUTES LATER:
By the way, I would prefer NOT to enclose all my code in a big try-catch and then close the windows after I've caught my error. The problem with this is I do like to go to debug mode on error, and caught errors don't bring me to debug mode.
Straight after you create Wordapp, use c = onCleanup(#()Wordapp.Quit). When your function exits, either naturally or with a crash, c will be deleted and its function will execute, quitting Word. If this is part of a script rather than a function, you can manually delete c to quit.
Also - while developing/debugging, I would set Wordapp.Visible to true so you can manually close word if necessary. Set back to false for production.
Use a handle class to delete them automatically.
classdef SafeWord < handle
properties(Access=public)
WordApp;
end
methods(Access=public)
function this = SafeWord(WordApp)
this.WordApp= WordApp;
end
function delete(this)
this.WordDoc.Close;
this.WordApp.Quit;
end
end
end
And the use case:
sw = SafeWord(Word.Application());
WordApplication = sw.WordApp;
% Do something here
% When sw ends its lifecycle, it calls delete.
Here is a related question.

Ruby: Read large data from stdout and stderr of an external process on Windows

Greetings, all,
I need to run a potentially long-running process from Ruby 1.9.2 on Windows and subsequently capture and parse the data from the external process's standard output and error. A large amount of data can be sent to each, but I am only necessarily interested in one line at a time (not capturing and storing the whole of the output).
After a bit of research, I found that the Open3 class would take care of executing the process and giving me IO objects connected to the process's standard output and error (via popen3).
Open3.popen3("external-program.bat") do |stdin, out, err, thread|
# Step3.profit() ?
end
However, I'm not sure how to continually read from both streams without blocking the program. Since calling IO#readlines on out or err when a lot of data has been sent results in a memory allocation error, I'm trying to continuously check both streams for available input, but not having much luck with any of my implementations.
Thanks in advance for any advice!
After a lot of different trial and error attempts, I eventually came up with using two threads, one to read from each stream (generator.rb is just a script I wrote to output things to standard out and err):
require 'open3'
data = {}
Open3.popen3("ruby generator.rb") do |stdin, out, err, external|
# Create a thread to read from each stream
{ :out => out, :err => err }.each do |key, stream|
Thread.new do
until (line = stream.gets).nil? do
data[key] = line
end
end
end
# Don't exit until the external process is done
external.join
end
puts data[:out]
puts data[:err]
It simply outputs the last line sent to standard output and error by the calling program, but could obviously be extended to do additional processing (with different logic in each thread). A method I was using before I finally came up with this was resulting in some failures due to race conditions; I don't know if this code is still vulnerable, but I've yet to experience a similar failure.

Resources