Yaws process died - erlang

I do performance testing of our Erlang application with OpenSTA. The test runs with 100 virtual users. At some point the following errors start popping up:
Yaws process died: {{badmatch,{error,eacces}},
[{yaws_server,ut_read,1},
{yaws_server,deliver_dyn_file,5},
{yaws_server,aloop,3},
{yaws_server,acceptor0,2},
{proc_lib,init_p_do_apply,3}]}
The test continues to run. I cannot find info about this error. Does eacces mean Error accessing a resource?
EDIT: As pointed out by #Muzaaya Joshua the call file:read_file(UT#urltype.fullpath) crashes in function ut_read(UT). I recompiled the module and printed the context. The error is eacces and UT holds:
{urltype,yaws,
{file_info,14088,regular,read_write,
{{2011,9,13},{11,51,42}},
{{2011,10,17},{17,59,44}},
{{2011,3,16},{13,18,58}},
33206,1,3,0,0,0,0},
"/handler.yaws",
"c:/Temp/harmony/script/../www/handler.yaws",
"/",undefined,undefined,"text/html",
"/handler.yaws",undefined}
This file handler.yaws is the entry point of our app and is called on every request. When I run the test with 100 or less virtual users I don't see these errors. So how can it be Missing permission for reading the file, or for searching one of the parent directories. as the error is described in the read_file documentation?
Thanks in advance.
Martin

eacces means access denied, the error codes are described at the end of the file documenation: http://www.erlang.org/doc/man/file.html#write_file_info-2

Yaws has failed to open a file. This is a file read permission denied to the user running yaws application. If you add permissions to the user running yaws to own all folders concerning yaws, this may be fixed. to check it out, try running yaws as root , if at all these paths are owned by root. The yaws_server.erl source file at the point is as follows:
ut_read(UT) ->
?Debug("ut_read() UT.fullpath = ~p~n", [UT#urltype.fullpath]),
case yaws:outh_get_content_encoding() of
identity ->
case UT#urltype.data of
undefined ->
?Debug("ut_read reading\n",[]),
{ok, Bin} = file:read_file(UT#urltype.fullpath),
?Debug("ut_read read ~p\n",[size(Bin)]),
Bin;
B when is_binary(B) ->
B
end;
deflate ->
case UT#urltype.deflate of
B when is_binary(B) ->
?Debug("ut_read using deflated binary of size ~p~n",
[size(B)]),
B
end
end.
The line in bold in the above source is where the bad match occurs.
Check wether yaws is running as a user with permissions to access its folders such as the doc root, ssl folders and other paths that yaws may access files. Does the user running yaws have access to all required files ?

In windows, this makes it easy. Now go to your Local disk C, Program Files (In windows 7, could be Program Files (x86)), lastly to where yaws is installed. This will be a folder: Yaws-VERSION e.g. Yaws-1.89. Now, when you right click this, you select Properties, then in the pop-up window you select Security. Under Security, you click edit. Now under Group or usernames, you select each user (and each type of account) and give it all permissions i.e. read, write, full control e.t.c. click Apply, wait for windows to perform the changes, then click Ok and close. Your users must now have all required permissions.

I managed to fix this errors by increasing the file size of the allowed in cache files in the YAWS configuration max_size_cached_file. This made our .yaws file to be loaded in memory and not accessess with file:read_file all the time. Hopefully this will save someone else couple of hours (or days :))

Related

Does Erlang's ssh_sftp library provide for a way to listen for directory changes?

I need to watch or listen to a folder on an SFTP server for any changes. At some given time in the future (I don't know when), the folder will be updated with a file. Instead of pinging every minute, how would I setup a listener or watcher on that folder so I know when it has that file? Does Erlang's ssh_sftp module provide a function for this?
Neither SFTP nor FTP protocol have any mechanism to notify a client about changes in a remote folder. The only solution to detect changes is to periodically enumerate remote directory tree and find differences.
Ref : https://winscp.net/eng/docs/library_example_watch_for_changes
I don't know whether you still need it or not but I have already implemented what you need. I won't be able to share the code due to legal agreements however I can hint you the way to implement it.
Requirement: Run a function whenever a file lands to a directory instead of polling the directory at a defined interval to make processing efficient.
Step 1: Start the ssh daemon process with sftp as a subsystem
{ok, Pid} = ssh:daemon(Port, [{user_passwords, [{User, Pass}]},
{system_dir, SystemDir},
{user_dir, UserDir},
{key_cb, cac_auth},
{shell, {cacsftpd_server, display_info, []}},
{subsystems, [ssh_sftpd:subsystem_spec([{cwd,
Home}, {file_handler, sftpd_file_handler}])]}])
Step 2: In sftpd_file_handler you can apply the trigger to call ur desired handler once the file is completely transferred ;)).
While not in Erlang, but rather Elixir, take a look at: https://github.com/Codenaut/exsftpd/blob/master/lib/sftpd_file_handler.ex
The essential bit is the write function:
defmodule Exsftpd.SftpFileHandler do
...
def write(io_device, data, state) do
{:file.write(io_device, data), state}
my_custom_function(state)
{:ok, state}
end
...
end
Here you can call whatever function you desire after (or instead of) writing the content to the filesystem.
Initialise the server like so: (see https://github.com/Codenaut/exsftpd/blob/master/lib/server.ex for a more elaborate example):
:ssh.daemon(2222,
system_dir: '/tmp/ssh',
subsystems: [
Exsftpd.SftpdChannel.subsystem_spec(
file_handler: {Exsftpd.SftpFileHandler, []}
)
],
user_dir: '/tmp/ssh/users'
)

How do I check if a network drive is online/offline without my program hanging?

I want to do some IO operations (reading files, listing folder content, etc) on a shared/network folder (\\JoulePC\Test\). If the folder is offline then the program will freeze for quite a while EVERY TIME I try to access it.
What I need to build is something like this:
function DriveIsOnline(Path: string): Boolean;
The function should return an answer quickly (under 1 second). I would use the DriveIsOnline before performing any IO operations on that remove folder.
__
The API function GetDriveType will return 1 (which means 'The root path is invalid') if the drive is offline. Will it be logically correct to consider this answer ('1') as an indication that the drive is offline?

Lua check if a file is open or not

I'm trying to script a lua file to check if a certain file is open. Then I want it to close that file if it is open. I know how to check if the file exist but I need to know how to check if the file is open, meaning the file is running.
Lua, like C, C++, and pretty much every other language, can only close files that it opens itself. You cannot close files open by other people (not with standard Lua calls); this would be incredibly rude.
So you can't test to see if a file is opened by someone else. Nor can you close their file. There may be system API calls you could make to do this, but you would have to give Lua scripts access to those APIs yourself. Lua's standard libraries can't do this.
Sounds like you want to check which if any programs have a given file open.
first thing that comes to mind is parsing the output of lsof on linux.
fd = io.popen("lsof path/to/my/file")
fileopened = (#fd:read("a*") > 0)
Kind of a hacky way to do it, but it works:
processname = "process_name_here.exe"
filedata = io.popen("tasklist /NH /FO CSV /FI \"IMAGENAME eq "..processname.."\"")
output = filedata:read()
filedata:close()
if output ~= "INFO: No tasks are running which match the specified criteria." then
-- Program is running. Close the program
os.execute("taskkill -im "..processname)
else
-- Program is not running
end
Just make sure to replace "process_name_here.exe" with the process name that shows up in task manager
Alternatively you can just use this to close it without checking if it was actually running:
os.execute("taskkill -im process_name_here.exe")

Problem installing windows service

I am having a problem installing a Windows service. I installed and uninstalled the service numerous times (installutil..... installutil /u) without any problem but something went wrong and now when I attempt to install, I get the error message listed below. I checked the computer management console, and service CIMediator does not appear on the list of services. How do I remove the service?
System.ArgumentException: Source CIMediator already exists on the local computer.
Just solved the same problem, also after a numerous uninstalls/installs/restarts.
I have my own implementation of service installer (derived from [System.Configuration.Install.Installer][1]), and I have specified application EventLog as following:
public ProjectInstaller()
{
InitializeComponent();
EventLogInstaller installer = FindInstaller(this.Installers);
if (installer != null)
{
installer.Log = "MyService";
}
}
You might have the same feature implemented the following way ([MSDN: EventLog.CreateEventSource Method] [2]):
if(!EventLog.SourceExists("MySource"))
{
EventLog.CreateEventSource("MySource", "MyNewLog");
}
In my case, during some of the installs EventLog was successfuly created, but during uninstall something went wrong, and EventLog was not removed (although it was not displaying in EventViewer, it was still present in the registry).
So the error "MyService already exists on the local computer", was obviously error about EventLog, not the service itself.
You could try to do the following:
Go to your Start menu and type regedit. This will open Registry Editor. Be careful with it, it is always recommended to back up the whole registry before doing anything (File -> Export), or only the keys you are about to edit/delete.
Open Edit -> Find , type CIMediator and leave only Keys checked. Your service name should appear as key multiple times, on following locations
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\eventlog\CIMediator,
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\CIMediator,
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\CIMediator,
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\CIMediator
Try to delete these keys. It worked for me.
1
2
Check to see if the key is still there in the registry.
HKLM\System\CurrentControlSet\Services\CIMediator (probably, unless the key is defined differently)
If it is, export the key to a .reg file and then delete it.

Spawn remote process w/o common file system

(nodeA#foo.hyd.com)8> spawn(nodeA#bar.del.com, tut, test, [hello, 5]).
I want to spawn a process on bar.del.com which has no file system access to foo.hyd.com (from where I am spawning the process), running subroutine "test" of module "tut".
Is there a way to do so, w/o providing the nodeA#bar.del.com with the compiled "tut" module file?
You can use the following function to load a module at remote node without providing the file itself:
load_module(Node, Module) ->
{_Module, Bin, Filename} = code:get_object_code(Module),
rpc:call(Node, code, load_binary, [Module, Filename, Bin]).
As noted in code:load_binary/3 Filename argument is used only to track the path to module and the file it points to is not used by local node_server.
I'm interpreting your question as a desire to not copy the *.beams from your filesystem to the remote file system.
If you are just testing things you can use the nl(Mod) call in the erl shell to load the module on all (currently) known nodes. That is, those that show up in nodes().
This will send the code over and load it from the memory copy, it will not store it in the remote filesystem.
You can also start the remote node using the slave module. A slave accesses its master's filesystem and code server. Ordinary auto-loading will then make sure the module exists in the slave when you call your test:tut/2 function.
You can send the local code to the remote node:
> {Mod, Bin, File} = code:get_object_code(Module).
> rpc:call(RemoteNode, code, load_binary, [Mod, File, Bin]).

Resources